'交易成功', '1000' => '报文解析失败', '1001' => '报文校验失败', '1002' => '输入项校验失败', '2000' => '贷款信息校验失败', '2001' => '权限不足', '2002' => '查询出错', '2003' => '信息有误', '9000' => '连接超时', '9002' => '报文超出最大长度', '9003' => '报文长度字节解析失败', '9004' => '解密报文失败', '9999' => '其他', ]; private $channelno = ''; // 渠道号 private $comno = ''; // 合作公司编号 private $api_uri = '/pmcs-tran/api/estimate'; private $api_url = ''; private $sm3; private $sm4; private $sm4_key = ''; public $orgInfoResp = []; // 机构信息array public function __construct() { $this->host = env('boc_consumer_finance.host'); $this->channelno = env('boc_consumer_finance.channelno'); $this->comno = env('boc_consumer_finance.comno'); $this->api_url = $this->host . $this->api_uri; // 国密 $this->sm4_key = env('boc_consumer_finance.sm4_key'); $this->sm3 = new Sm3(); $this->sm4 = new MySm4($this->sm4_key); } public function checkRequestHeader($header, $content) { $estimate_timestamp = $header['estimate_timestamp'] ?? ($header['estimate-timestamp'] ?? ''); $estimate_sign = $header['estimate_sign'] ?? ($header['estimate-sign'] ?? ''); if (empty($estimate_timestamp)) { Log::error('header estimate_timestamp miss:' . json_encode($header, 256)); return false; } if (empty($estimate_sign)) { Log::error('header estimate_sign miss:' . json_encode($header, 256)); return false; } $unmarshal_content = $this->sm4->decrypt($content); if ( $this->sm3->sign($estimate_timestamp . $unmarshal_content) != $estimate_sign ) { Log::error('header estimate_sign error:' . json_encode($header, 256)); return false; } return true; } /** * 检查请求参数是否完整 * @param $params * @return bool */ public function checkRequestParams($params): bool { if (empty($params['tranno'])) { return false; } if (empty($params['content'])) { return false; } return true; } /** * 检查中行接口返回数据格式是否正确 * @param array $result * @param string $tranno * @return bool */ public function checkBocResponse(array $result, string $tranno): bool { if (empty($result)) { Log::error("{$tranno}接口返回为空"); return false; } if (empty($result['retcode'])) { Log::error("{$tranno}接口返回数据格式错误,缺少retcode"); return false; } if (empty($result['osn'])) { Log::error("{$tranno}接口返回数据格式错误,缺少osn"); return false; } if (empty($result['note'])) { Log::error("{$tranno}接口返回数据格式错误,缺少note"); return false; } if ($result['retcode'] != '0000') { Log::error("{$tranno}接口返回失败,retcode={$result['retcode']}"); Log::error("{$tranno}接口返回失败,osn={$result['osn']}"); Log::error("{$tranno}接口返回失败,note={$result['note']}"); return false; } switch ($tranno) { case self::INQUIRY_RESULT_FEEDBACK: if (empty($result['enquiryInfoResp'])) { Log::error("{$tranno}接口返回数据格式错误,缺少enquiryInfoResp"); return false; } // if (empty($result['enquiryInfoResp']['dealNo'])) { // Log::error("{$tranno}接口返回数据格式错误,enquiryInfoResp中缺少dealNo"); // return false; // } if (empty($result['enquiryInfoResp']['estimateDealNo'])) { Log::error("{$tranno}接口返回数据格式错误,enquiryInfoResp中缺少estimateDealNo"); return false; } if (empty($result['enquiryInfoResp']['Result'])) { Log::error("{$tranno}接口返回数据格式错误,enquiryInfoResp中缺少Result"); return false; } break; case self::EVA_REPORT_SUCCESS_PROVIDE: if (empty($result['estimateinfoResp'])) { Log::error("{$tranno}接口返回数据格式错误,缺少estimateinfoResp"); return false; } // if (empty($result['estimateinfoResp']['dealNo'])) { // Log::error("{$tranno}接口返回数据格式错误,estimateinfoResp中缺少dealNo"); // return false; // } if (empty($result['estimateinfoResp']['estimateDealNo'])) { Log::error("{$tranno}接口返回数据格式错误,estimateinfoResp中缺少estimateDealNo"); return false; } if (empty($result['estimateinfoResp']['estimateReportNo'])) { Log::error("{$tranno}接口返回数据格式错误,estimateinfoResp中缺少estimateReportNo"); return false; } if (empty($result['estimateinfoResp']['result'])) { Log::error("{$tranno}接口返回数据格式错误,estimateinfoResp中缺少result"); return false; } break; case self::ACCOUNT_MANAGER_INFO_SEARCH: if (!isset($result['orgInfoResp'])) { Log::error("{$tranno}接口返回数据格式错误,缺少orgInfoResp"); return false; } break; } return true; } /** * 解开来自客户端的数据 * @param $content string 加密数据 * @return mixed */ public function parseContentString(string $content) { $decode_str = $this->sm4->decrypt($content); return json_decode($decode_str, true); // sm4解密 } /** * 组装发送给中行的请求数据中的contents * @param $tranno * @param $isn * @param $biz_request_params * @return array 【encrypt】加密的content,【decrypt】解密的content */ public function marshalContents($tranno, $isn, $biz_request_params): array { $result = array_merge([ 'tranno' => $tranno, 'channelno' => $this->channelno, 'comno' => $this->comno, 'isn' => $isn, ], $biz_request_params); $content = $this->sm4->encrypt(json_encode($result, 256)); // sm4加密 return [ 'encrypt' => $content, 'decrypt' => $result, ]; } /** * 组装发送给中行的返回数据(用于返回客户端) * @param $retcode string 返回码 * @param $tranno string 交易号,识别交易类型 * @param $osn string 输出序号 * @param $req_encrypt_content string 中行业务请求的加密的content * @param $biz_response_data array 我方业务返回的数据 * @return \think\response */ public function buildResponseData( string $retcode, string $tranno = '', string $osn = '', string $req_encrypt_content = '', array $biz_response_data = [] ): \think\response { $result = array_merge([ 'retcode' => $retcode, 'tranno' => $tranno, 'osn' => $osn, 'channelno' => $this->channelno, 'comno' => $this->comno, 'note' => self::RETURN_CODE_ARRAY[$retcode] ?? '', ], $biz_response_data); $estimate_timestamp = (int)round(microtime(true) * 1000); $estimate_sign = $this->sm3->sign($estimate_timestamp . json_encode($result, 256)); $header['content-type'] = 'application/x-www-form-urlencoded'; $header['estimate-timestamp'] = $estimate_timestamp; $header['estimate-sign'] = $estimate_sign; $resp_encrypt_content = $this->sm4->encrypt(json_encode($result, 256)); // sm4加密 Log::debug('biz_response_data:'); Log::debug($biz_response_data); Log::debug('header:'); Log::debug($header); Log::debug('resp_encrypt_content:'); Log::debug($resp_encrypt_content); if (!empty($resp_encrypt_content)) { $req_content_arr = $this->parseContentString($req_encrypt_content); $isn = ''; if (!empty($req_content_arr['isn'])) { $isn = $req_content_arr['isn']; } $insert_boc_cf_req_resp = [ 'direct' => 2, 'estimate_timestamp' => $estimate_timestamp, 'estimate_sign' => $estimate_sign, 'req_encrypt_content' => $req_encrypt_content, 'req_decrypt_content' => json_encode($this->parseContentString($req_encrypt_content), JSON_UNESCAPED_UNICODE), 'resp_encrypt_content' => $resp_encrypt_content, 'resp_decrypt_content' => json_encode($result, JSON_UNESCAPED_UNICODE), 'retcode' => $result['retcode'], 'tranno' => $tranno, 'channelno' => $result['channelno'], 'comno' => $result['comno'], 'isn' => $isn, 'osn' => $result['osn'], 'note' => $result['note'], 'create_time' => date('Y-m-d H:i:s'), 'update_time' => date('Y-m-d H:i:s'), ]; Db::name('boc_cf_req_resp')->insert($insert_boc_cf_req_resp); } return Response::create($resp_encrypt_content, '', 200, $header); } /** * 中行方请求:询价申请 * @param array $data * @return \think\response */ public function inquiryApply(array $data): \think\response { $tranno = $data['tranno']; $osn = $this->genOsn(); $req_encrypt_content = $data['content']; $content_arr = $this->parseContentString($req_encrypt_content); if (empty($content_arr['enquiryInfoReq'])) { Log::error('inquiryApply content_arr error:' . json_encode($content_arr)); return $this->buildResponseData('1002', $tranno, $osn, $req_encrypt_content, []); } $validate = new BocCfValidate(); if (!$validate->scene('inquire_apply')->check($content_arr['enquiryInfoReq'])) { Log::error('inquiryApply validate error:' . json_encode($validate->getError())); return $this->buildResponseData('1002', $tranno, $osn, $req_encrypt_content, []); } $enquiryInfoResp = [ 'enquiryInfoResp' => [ 'dealNo' => $content_arr['enquiryInfoReq']['dealNo'], 'estimateDealNo' => '', 'roomArea' => 0, 'unitPrice' => 0, 'totalPrice' => 0, 'price1' => 0, 'price2' => 0, 'tax' => 0, 'status' => '03', 'evalTime' => '', 'name' => '', 'telephoneNumber' => '', 'intentFileType' => '03', 'houseAddr' => '', 'coveredArea' => 0, 'completionDate' => '', 'regPrice' => 0, 'landNo' => '', 'landLimitDate' => '', 'landBgnDate' => '', 'landEndDate' => '', 'houseProperty' => '', 'registDate' => '', 'houseUse' => '', 'ownerName' => '', 'Result' => 'N', 'Reason' => '', ], ]; Db::startTrans(); // 1.中行消金询价申请表插入一条数据 $boc_cf_inquiry_apply_model = new BocCfInquiryApply(); $boc_cf_inquiry_apply_model->dealNo = $content_arr['enquiryInfoReq']['dealNo']; $boc_cf_inquiry_apply_model->fileType = $content_arr['enquiryInfoReq']['fileType']; $boc_cf_inquiry_apply_model->fileName = $content_arr['enquiryInfoReq']['fileName']; $boc_cf_inquiry_apply_model->fileContent = $content_arr['enquiryInfoReq']['fileContent']; $boc_cf_inquiry_apply_model->estimateTimes = $content_arr['enquiryInfoReq']['estimateTimes']; $boc_cf_inquiry_apply_model->message = $content_arr['enquiryInfoReq']['message']; $boc_cf_inquiry_apply_model->tlrname = $content_arr['enquiryInfoReq']['tlrname']; $boc_cf_inquiry_apply_model->oprTel = $content_arr['enquiryInfoReq']['oprTel'] ?? ''; $boc_cf_inquiry_apply_model->bnkno = $content_arr['enquiryInfoReq']['bnkno']; $boc_cf_inquiry_apply_model->type = $content_arr['enquiryInfoReq']['type']; // if (preg_match('/^data:(.+);base64,/', $content_arr['enquiryInfoReq']['fileContent'], $matches)) { // $mime_type = $matches[1] ?? 'application/octet-stream'; // $image_data = base64_decode(str_replace($matches[0], '', $content_arr['enquiryInfoReq']['fileContent'])); if (!empty($content_arr['enquiryInfoReq']['fileContent'])) { if (preg_match('/^data:(.+);base64,/', $content_arr['enquiryInfoReq']['fileContent'], $matches)) { $mime_type = $matches[1] ?? 'application/octet-stream'; $image_data = base64_decode(str_replace($matches[0], '', $content_arr['enquiryInfoReq']['fileContent'])); } else { $mime_type = 'image/png'; $image_data = "data:{$mime_type};base64," . $content_arr['enquiryInfoReq']['fileContent']; } $temp_file = str_replace('\\', '/', tempnam(sys_get_temp_dir(), 'cos_')); file_put_contents($temp_file, $image_data); $ossPath = '/uploads' . '/' . date('Ymd') . '/' . $content_arr['enquiryInfoReq']['fileName']; try { $oss_service = new OssService(); $url = $oss_service->uploadSingleFile($ossPath, $temp_file, $mime_type); } catch (\Exception $e) { Log::error('错误文件:' . $e->getFile()); Log::error('错误行数:' . $e->getLine()); Log::error('错误编码:' . $e->getCode()); Log::error('错误信息:' . $e->getMessage()); return $this->buildResponseData('9999', $tranno, $osn, $req_encrypt_content, []); } finally { if (file_exists($temp_file)) { unlink($temp_file); } } $boc_cf_inquiry_apply_model->fileUrl = str_replace('\\', '/', $url); } if (!$boc_cf_inquiry_apply_model->save()) { Db::rollback(); Log::error('inquiryApply save error:' . json_encode($boc_cf_inquiry_apply_model->getError())); $enquiryInfoResp['enquiryInfoResp']['Reason'] = '询价数据保存失败'; return $this->buildResponseData('2003', $tranno, $osn, $req_encrypt_content, $enquiryInfoResp); } // 2.询价表只生成一个询价编号,并插入一条数据 $sz_company_id = Db::name('branchcom_config')->where('full_name', '深圳公司')->value('id'); $inquiry_model = new Inquiry(); $order_no = $inquiry_model->generateInquiryNo($sz_company_id); $inquiry_model->order_no = $order_no; $en_order_no = (new InquiryService())->enOrderNo($order_no); $inquiry_model->order_no_en = $en_order_no; $inquiry_model->user_id = 0; $inquiry_model->user_name = ''; $inquiry_model->create_time = date('Y-m-d H:i:s'); $inquiry_model->update_time = date('Y-m-d H:i:s'); if (!$inquiry_model->save()) { Db::rollback(); Log::error('inquiryApply save error:' . json_encode($inquiry_model->getError())); $enquiryInfoResp['enquiryInfoResp']['Reason'] = '询价数据保存失败'; return $this->buildResponseData('9999', $tranno, $osn, $req_encrypt_content, $enquiryInfoResp); } $enquiryInfoResp['enquiryInfoResp']['Result'] = 'Y'; $enquiryInfoResp['enquiryInfoResp']['estimateDealNo'] = $en_order_no; Db::commit(); return $this->buildResponseData('0000', $tranno, $osn, $req_encrypt_content, $enquiryInfoResp); } /** * 我方请求中行方:询价结果反馈 * @param string $dealNo * @return bool */ public function inquiryResultFeedback(string $dealNo): bool { $tranno = self::INQUIRY_RESULT_FEEDBACK; $isn = $this->genIsn(); try { $inquiry_info = Db::name('inquiry') ->where('business_no', $dealNo) ->find(); if (empty($inquiry_info)) { Log::error('查询不到询价信息'); return false; } $boc_cf_inquiry_apply_info = Db::name('boc_cf_inquiry_apply') ->where('dealNo', $dealNo) ->find(); if (empty($boc_cf_inquiry_apply_info)) { Log::error('查询不到中行消金询价申请信息'); return false; } $property_cert_info = Db::name('property_cert_info') ->where('quot_id', $inquiry_info['id']) ->find(); if (empty($property_cert_info)) { Log::error('查询不到录入的物业信息'); return false; } $valuer_ids = isset($property_cert_info['appraiser_ids']) && !empty($property_cert_info['appraiser_ids']) ? explode(',', $property_cert_info['appraiser_ids']) : []; $valuer_name = ''; $valuer_mobile = ''; if (count($valuer_ids) > 0) { $valuer_info = Db::name('valuer') ->field('name, mobile') ->where('id', $valuer_ids[0]) ->find(); if (!empty($valuer_info)) { $valuer_name = $valuer_info['name']; $valuer_mobile = $valuer_info['mobile']; } } } catch (\Exception $e) { Log::error('错误文件:' . $e->getFile()); Log::error('错误行数:' . $e->getLine()); Log::error('错误编码:' . $e->getCode()); Log::error('错误信息:' . $e->getMessage()); return false; } $enquiryInfoReq = [ 'enquiryInfoReq' => [ 'dealNo' => $dealNo, // 'estimateDealNo' => $inquiry_info['order_no_en'], // 'roomArea' => $property_cert_info['size'], 'unitPrice' => $property_cert_info['eva_unit_price'], 'totalPrice' => $property_cert_info['eva_total_value'], 'price1' => $property_cert_info['eva_net_value'], 'price2' => $property_cert_info['eva_net_value2'], 'tax' => $property_cert_info['total_taxes1'] ? $property_cert_info['total_taxes1'] : ($property_cert_info['total_taxes2'] ?? 0), 'status' => $inquiry_info['is_auto'] == 0 ? '03' : '01', //01-自动估价并返回 02-自动估价失败(转人工) 03-人工估价完成 'evalTime' => date('Ymd', $property_cert_info['r_create_time']), 'name' => $valuer_name, 'telephoneNumber' => $valuer_mobile, 'intentFileType' => $inquiry_info['is_simple'] == 0 ? '02' : '01', // 01-只能是简易报告 02-只能是正式报告 03-简易或正式报告都可以 'houseAddr' => $property_cert_info['property_full_name'], 'coveredArea' => $property_cert_info['size'], 'completionDate' => date('Ymd', strtotime($property_cert_info['completion_time'])), 'regPrice' => $property_cert_info['reg_price'], 'landNo' => $property_cert_info['parcel_no'], 'landLimitDate' => '', 'landBgnDate' => '', 'landEndDate' => '', 'houseProperty' => $property_cert_info['use_right_source'], 'registDate' => date('Ymd', strtotime($property_cert_info['purchase_date'])), 'houseUse' => $property_cert_info['usage'], 'ownerName' => $property_cert_info['owner_name'], ] ]; $enquiryInfoReq['enquiryInfoReq'] = $this->removeNull($enquiryInfoReq['enquiryInfoReq']); $contents = $this->marshalContents($tranno, $isn, $enquiryInfoReq); Log::debug("------content_original-----"); Log::debug(json_encode($contents['decrypt'], 256)); Log::debug("------content_encrypt-----"); Log::debug($contents['encrypt']); // 签名 $estimate_timestamp = (int)round(microtime(true) * 1000); $estimate_sign = $this->sm3->sign($estimate_timestamp . json_encode($contents['decrypt'], 256)); $header[] = "Content-Type: application/x-www-form-urlencoded; charset=utf-8"; $header[] = "estimate-timestamp: {$estimate_timestamp}"; $header[] = "estimate-sign: {$estimate_sign}"; $curl_result = curlRequest($this->api_url, 'post', http_build_query([ 'tranno' => $tranno, 'content' => $contents['encrypt'] ]), $header); $result_string = $curl_result['data']; Log::debug("------estimate-timestamp-----"); Log::debug($estimate_timestamp); Log::debug("------estimate-sign-----"); Log::debug($estimate_sign); Log::debug("------api_url-----"); Log::debug($this->api_url); Log::debug("------result_string_need_to_decrypt-----"); Log::debug($result_string); $result = $this->parseContentString($result_string); Log::debug('--------result_has_been_decrypt--------'); Log::debug($result); if (empty($result)) { Log::error('响应数据解析为空'); return false; } $check_result = $this->checkBocResponse($result, $tranno); if (!$check_result) { return false; } $insert_boc_cf_req_resp = [ 'direct' => 1, 'estimate_timestamp' => $estimate_timestamp, 'estimate_sign' => $estimate_sign, 'req_encrypt_content' => $contents['encrypt'], 'req_decrypt_content' => json_encode($contents['decrypt'], JSON_UNESCAPED_UNICODE), 'resp_encrypt_content' => $result_string, 'resp_decrypt_content' => json_encode($result, JSON_UNESCAPED_UNICODE), 'retcode' => $result['retcode'], 'tranno' => $tranno, 'channelno' => $result['channelno'], 'comno' => $result['comno'], 'isn' => $isn, 'osn' => $result['osn'], 'note' => $result['note'], 'create_time' => date('Y-m-d H:i:s'), 'update_time' => date('Y-m-d H:i:s'), ]; $res = Db::name('boc_cf_req_resp')->insert($insert_boc_cf_req_resp); if (!$res) { Log::error('保存中行消金询价申请返回数据失败'); return false; } return true; } /** * 我方请求中行方:主动推送预估单报告 * @param string $quotId 询价单id * @param string $bnkno 支行机构号 * @param string $tlrname 客户经理名称 * @return bool */ public function sendEstimateReport(string $quotId, string $bnkno, string $tlrname): bool { $tranno = self::ESTIMATE_REPORT_SUCCESS_PROVIDE; $isn = $this->genIsn(); try { $inquiry_info = Db::name('inquiry') ->where('id', $quotId) ->find(); if (empty($inquiry_info)) { Log::error('查询不到询价信息'); return false; } if (empty($inquiry_info['estimate_url'])) { Log::error('预估单报告未上传'); return false; } $boc_cf_inquiry_apply_info = Db::name('boc_cf_inquiry_apply') ->where('dealNo', $inquiry_info['business_no']) ->find(); /*if (empty($boc_cf_inquiry_apply_info)) { Log::error('查询不到中行消金询价申请信息'); return false; }*/ $property_cert_info = Db::name('property_cert_info') ->where('quot_id', $inquiry_info['id']) ->find(); if (empty($property_cert_info)) { Log::error('查询不到录入的物业信息'); return false; } $path = parse_url(str_replace('\\', '/', $inquiry_info['estimate_url']), PHP_URL_PATH); $house_usage_dict_list = Db::name('dictionary')->where('type', 'HOUSE_USAGE')->column('code,valname'); $houseUsageType = '01'; //住宅 if (array_key_exists($property_cert_info['usage'], $house_usage_dict_list) && $house_usage_dict_list[$property_cert_info['usage']] != '住宅') { $houseUsageType = '02'; //非住宅 } $estimateinfoReq = [ 'estimateinfoReq' => [ 'dealNo' => $inquiry_info['business_no'] ?? null, // 'estimateDealNo' => $inquiry_info['order_no_en'], // 'fileName' => basename($path), 'fileType' => '03', 'bnkno' => $boc_cf_inquiry_apply_info['bnkno'] ?? $bnkno, 'tlrname' => $boc_cf_inquiry_apply_info['tlrname'] ?? $tlrname, 'estimateReportNo' => $inquiry_info['estimated_no'], 'address' => $property_cert_info['land_location'] . $property_cert_info['property_full_name'], 'area' => $property_cert_info['size'], 'unitPrice' => $property_cert_info['eva_unit_price'], 'totalPrice' => $property_cert_info['eva_total_value'], 'ownerName' => $property_cert_info['owner_name'], 'houseUseType' => $houseUsageType, 'houseUse' => $property_cert_info['cert_usage'], ] ]; SyncHttpService::post('admin/Boccf/syncSendFileToBoccf', [ 'file_url' => $inquiry_info['estimate_url'], 'isn' => $isn, 'tranno' => $tranno, 'estimateinfoReq' => $estimateinfoReq, ]); Db::startTrans(); $update_inquiry = [ 'biz_status' => 30, 'update_time' => date('Y-m-d H:i:s'), ]; if (empty($inquiry_info['bnkno'])) { $update_inquiry['bnkno'] = $bnkno; } if (empty($inquiry_info['tlrname'])) { $update_inquiry['tlrname'] = $tlrname; } $res = Db::name('inquiry')->where('id', $quotId)->update($update_inquiry); if (!$res) { Db::rollback(); Log::error('更新询价信息失败'); return false; } if (!empty($inquiry_info['business_no'])) { $res = Db::name('boc_cf_inquiry_apply')->where('dealNo', $inquiry_info['business_no'])->update([ 'biz_status' => 30, 'update_time' => date('Y-m-d H:i:s'), ]); if (!$res) { Db::rollback(); Log::error('更新中行消金询价申请状态失败'); return false; } } Db::commit(); } catch (\Exception $e) { Log::error('错误文件:' . $e->getFile()); Log::error('错误行数:' . $e->getLine()); Log::error('错误编码:' . $e->getCode()); Log::error('错误信息:' . $e->getMessage()); return false; } return true; } /** * 中行方请求我方:申请出具评估报告 * @param array $data * @return \think\response */ public function applyToProvideEvaReport(array $data): \think\response { $tranno = $data['tranno']; $osn = $this->genOsn(); $req_encrypt_content = $data['content']; $content_arr = $this->parseContentString($req_encrypt_content); if (empty($content_arr['assessInfoReq'])) { Log::error('applyToProvideEvaReport content_arr error:' . json_encode($content_arr)); return $this->buildResponseData('1002', $tranno, $osn, $req_encrypt_content, []); } $validate = new BocCfValidate(); if (!$validate->scene('apply_to_provide_eva_report')->check($content_arr['assessInfoReq'])) { Log::error('applyToProvideEvaReport validate error:' . json_encode($validate->getError())); return $this->buildResponseData('1002', $tranno, $osn, $req_encrypt_content, []); } $dealNo = null; if (!empty($content_arr['assessInfoReq']) && !empty($content_arr['assessInfoReq']['dealNo'])) { $dealNo = $content_arr['assessInfoReq']['dealNo']; } $assessInfoResp = [ 'assessInfoResp' => [ 'dealNo' => $dealNo, 'estimateDealNo' => $content_arr['assessInfoReq']['estimateDealNo'], 'Result' => 'N', 'Reason' => '', ], ]; try { Db::startTrans(); $inquiry_info = Db::name('inquiry') ->where('order_no_en', $content_arr['assessInfoReq']['estimateDealNo']) ->find(); if (empty($inquiry_info)) { Db::rollback(); Log::error('applyToProvideEvaReport:查询不到询价信息'); return $this->buildResponseData('2003', $tranno, $osn, $req_encrypt_content, $assessInfoResp); } $assessInfoResp['assessInfoResp']['Result'] = 'Y'; $res = Db::name('inquiry')->where('id', $inquiry_info['id'])->update([ 'biz_status' => 40, 'update_time' => date('Y-m-d H:i:s'), ]); if (!$res) { Db::rollback(); Log::error('inquiry update error'); $assessInfoResp['assessInfoResp']['Reason'] = '內部处理失败'; return $this->buildResponseData('9999', $tranno, $osn, $req_encrypt_content, $assessInfoResp); } if (!empty($dealNo)) { $boc_cf_inquiry_apply_model = new BocCfInquiryApply(); $res = $boc_cf_inquiry_apply_model->where('dealNo', $dealNo)->update([ 'biz_status' => 40, 'update_time' => date('Y-m-d H:i:s'), ]); if (!$res) { Db::rollback(); Log::error('applyToProvideEvaReport update error:' . json_encode($boc_cf_inquiry_apply_model->getError())); $assessInfoResp['assessInfoResp']['Reason'] = '內部处理失败'; return $this->buildResponseData('9999', $tranno, $osn, $req_encrypt_content, $assessInfoResp); } } Db::commit(); return $this->buildResponseData('0000', $tranno, $osn, $req_encrypt_content, $assessInfoResp); } catch (\Exception $e) { Db::rollback(); Log::error('错误文件:' . $e->getFile()); Log::error('错误行数:' . $e->getLine()); Log::error('错误编码:' . $e->getCode()); Log::error('错误信息:' . $e->getMessage()); return $this->buildResponseData('9999', $tranno, $osn, $req_encrypt_content, $assessInfoResp); } } /** * 我方请求中行方:发送正式报告 * @param string $report_no 报告编号 * @param string $bnkno 支行机构号 * @param string $tlrname 客户经理名称 * @return bool */ public function evaReportSuccessProvide(string $report_no, string $bnkno, string $tlrname): bool { $tranno = self::EVA_REPORT_SUCCESS_PROVIDE; $isn = $this->genIsn(); try { $report_info = Db::name('report') ->where('report_no', $report_no) ->find(); if (empty($report_info)) { Log::error('查询不到报告信息'); return false; } $report_detail_info = Db::name('report_detail') ->where('report_id', $report_info['id']) ->find(); if (empty($report_detail_info)) { Log::error('查询不到报告信息'); return false; } $inquiry_info = Db::name('inquiry') ->where('id', $report_info['quot_id']) ->find(); if (empty($inquiry_info)) { Log::error('查询不到询价信息'); return false; } $property_cert_info = Db::name('property_cert_info') ->where('quot_id', $inquiry_info['id']) ->find(); if (empty($property_cert_info)) { Log::error('查询不到录入的物业信息'); return false; } $boc_cf_inquiry_apply_info = Db::name('boc_cf_inquiry_apply') ->where('dealNo', $inquiry_info['business_no']) ->find(); // if (empty($boc_cf_inquiry_apply_info)) { // Log::error('查询不到中行消金询价申请信息'); // return false; // } } catch (\Exception $e) { Log::error('错误文件:' . $e->getFile()); Log::error('错误行数:' . $e->getLine()); Log::error('错误编码:' . $e->getCode()); Log::error('错误信息:' . $e->getMessage()); return false; } $report_url = $report_info['report_url']; if (!empty($report_info['upload_report_url'])) { $report_url = $report_info['upload_report_url']; } $path = parse_url(str_replace('\\', '/', $report_url), PHP_URL_PATH); $house_usage_dict_list = Db::name('dictionary')->where('type', 'HOUSE_USAGE')->column('code,valname'); $houseUsageType = '01'; //住宅 if (array_key_exists($property_cert_info['usage'], $house_usage_dict_list) && $house_usage_dict_list[$property_cert_info['usage']] != '住宅') { $houseUsageType = '02'; //非住宅 } // 提取路径部分(不含域名和参数) $estimateinfoReq = [ 'estimateinfoReq' => [ 'dealNo' => $inquiry_info['business_no'] ?? null, // 'estimateDealNo' => $inquiry_info['order_no_en'], // 'fileName' => basename($path), 'fileType' => '02', 'bnkno' => $boc_cf_inquiry_apply_info['bnkno'] ?? ($inquiry_info['bnkno'] ?? ($bnkno?? null)), 'tlrname' => $boc_cf_inquiry_apply_info['tlrname'] ?? ($inquiry_info['tlrname'] ?? ($tlrname ?? null)), 'estimateReportNo' => $report_no, 'address' => $report_detail_info['land_location'] . $property_cert_info['property_full_name'], 'area' => $property_cert_info['size'], 'unitPrice' => $property_cert_info['eva_unit_price'], 'totalPrice' => $property_cert_info['eva_total_value'], 'ownerName' => $property_cert_info['owner_name'], 'houseUseType' => $houseUsageType, 'houseUse' => $property_cert_info['cert_usage'], ] ]; SyncHttpService::post('admin/Boccf/syncSendFileToBoccf', [ 'file_url' => str_replace('\\', '/', $report_url), 'isn' => $isn, 'tranno' => $tranno, 'estimateinfoReq' => $estimateinfoReq ]); Db::startTrans(); $update_inquiry = [ 'is_send_report_to_boc' => 1, 'biz_status' => 50, 'update_time' => date('Y-m-d H:i:s'), ]; if (!empty($bnkno)) { $update_inquiry['bnkno'] = $bnkno; } if (!empty($tlrname)) { $update_inquiry['tlrname'] = $tlrname; } $res = Db::name('inquiry')->where('id', $inquiry_info['id'])->update($update_inquiry); if (!$res) { Db::rollback(); Log::error('更新询价业务状态失败'); return false; } if (!empty($inquiry_info['business_no'])) { $res = Db::name('boc_cf_inquiry_apply')->where('dealNo', $inquiry_info['business_no'])->update([ 'biz_status' => 50, 'update_time' => date('Y-m-d H:i:s'), ]); if (!$res) { Db::rollback(); Log::error('更新中行消金询价申请状态失败'); return false; } } Db::commit(); return true; } /* * 我方请求中行方,获取客户经理信息 */ public function getAccountManagerInfo(string $name) { $tranno = self::ACCOUNT_MANAGER_INFO_SEARCH; $isn = $this->genIsn(); $orgInfoReq = [ 'orgInfoReq' => [ 'tlrname' => $name, ], ]; $contents = $this->marshalContents($tranno, $isn, $orgInfoReq); Log::debug("------content_original-----"); Log::debug(json_encode($contents['decrypt'], 256)); Log::debug("------content_encrypt_base64_encode-----"); Log::debug($contents['encrypt']); // 签名 $estimate_timestamp = (int)round(microtime(true) * 1000); $estimate_sign = $this->sm3->sign($estimate_timestamp . json_encode($contents['decrypt'], 256)); $header[] = "Content-Type: application/x-www-form-urlencoded; charset=utf-8"; $header[] = "estimate-timestamp: {$estimate_timestamp}"; $header[] = "estimate-sign: {$estimate_sign}"; $curl_result = curlRequest($this->api_url, 'post', http_build_query([ 'tranno' => $tranno, 'content' => $contents['encrypt'] ]), $header); $result_string = $curl_result['data']; Log::debug("------estimate-timestamp-----"); Log::debug($estimate_timestamp); Log::debug("------estimate-sign-----"); Log::debug($estimate_sign); Log::debug("------api_url-----"); Log::debug($this->api_url); Log::debug("------result_string_need_to_decrypt-----"); Log::debug($result_string); $result = $this->parseContentString($result_string); Log::debug('--------result_has_been_decrypt--------'); Log::debug($result); if (empty($result)) { Log::error('响应数据解析为空'); return false; } $check_result = $this->checkBocResponse($result, $tranno); if (!$check_result) { return false; } $this->orgInfoResp = $result['orgInfoResp']; $insert_boc_cf_req_resp = [ 'direct' => 1, 'estimate_timestamp' => $estimate_timestamp, 'estimate_sign' => $estimate_sign, 'req_encrypt_content' => $contents['encrypt'], 'req_decrypt_content' => json_encode($contents['decrypt'], JSON_UNESCAPED_UNICODE), 'resp_encrypt_content' => $result_string, 'resp_decrypt_content' => json_encode($result, JSON_UNESCAPED_UNICODE), 'retcode' => $result['retcode'], 'tranno' => $tranno, 'channelno' => $result['channelno'], 'comno' => $result['comno'], 'osn' => $result['osn'], 'note' => $result['note'], 'create_time' => date('Y-m-d H:i:s'), 'update_time' => date('Y-m-d H:i:s'), ]; $res = Db::name('boc_cf_req_resp')->insert($insert_boc_cf_req_resp); if (!$res) { Log::error('保存中行消金返回数据失败'); return false; } return true; } public function genIsn() { $isn = date('YmdHis') . substr(microtime(true), 11); // $isn = uniqid('isn_', true); return $isn; } public function genOsn() { $osn = date('YmdHis') . substr(microtime(true), 11); // $osn = uniqid('osn_', true); return $osn; } private function removeNull($data) { foreach ($data as $key => $value) { if (is_null($value)) { unset($data[$key]); } } return $data; } public function syncSendBoccfFileRequest($file_url, $isn, $tranno, $estimateinfoReq) { $file_content = base64_encode(file_get_contents($file_url)); $estimateinfoReq['estimateinfoReq']['fileContent'] = $file_content; $estimateinfoReq['estimateinfoReq'] = $this->removeNull($estimateinfoReq['estimateinfoReq']); $contents = $this->marshalContents($tranno, $isn, $estimateinfoReq); Log::debug("------content_original-----"); Log::debug(json_encode($contents['decrypt'], 256)); Log::debug("------content_encrypt_base64_encode-----"); Log::debug($contents['encrypt']); // 签名 $estimate_timestamp = (int)round(microtime(true) * 1000); $estimate_sign = $this->sm3->sign($estimate_timestamp . json_encode($contents['decrypt'], 256)); $header[] = "Content-Type: application/x-www-form-urlencoded; charset=utf-8"; $header[] = "estimate-timestamp: {$estimate_timestamp}"; $header[] = "estimate-sign: {$estimate_sign}"; $curl_result = curlRequest($this->api_url, 'post', http_build_query([ 'tranno' => $tranno, 'content' => $contents['encrypt'] ]), $header, [], [], 0); $result_string = $curl_result['data']; Log::debug("------estimate-timestamp-----"); Log::debug($estimate_timestamp); Log::debug("------estimate-sign-----"); Log::debug($estimate_sign); Log::debug("------api_url-----"); Log::debug($this->api_url); Log::debug("------result_string_need_to_decrypt-----"); Log::debug($result_string); $result = $this->parseContentString($result_string); Log::debug('--------result_has_been_decrypt--------'); Log::debug($result); if (empty($result)) { Log::error('响应数据解析为空'); return false; } $check_result = $this->checkBocResponse($result, $tranno); if (!$check_result) { return false; } $insert_boc_cf_req_resp = [ 'direct' => 1, 'estimate_timestamp' => $estimate_timestamp, 'estimate_sign' => $estimate_sign, // 'req_encrypt_content' => $contents['encrypt'], // 'req_decrypt_content' => json_encode($contents['decrypt'], JSON_UNESCAPED_UNICODE), 'resp_encrypt_content' => $result_string, 'resp_decrypt_content' => json_encode($result, JSON_UNESCAPED_UNICODE), 'retcode' => $result['retcode'], 'tranno' => $tranno, 'channelno' => $result['channelno'], 'comno' => $result['comno'], 'isn' => $isn, 'osn' => $result['osn'], 'note' => $result['note'], 'create_time' => date('Y-m-d H:i:s'), 'update_time' => date('Y-m-d H:i:s'), ]; $res = Db::name('boc_cf_req_resp')->insert($insert_boc_cf_req_resp); if (!$res) { Log::error('保存中行消金返回数据失败'); return false; } return true; } }