base_url = env('boc_common.base_url'); $this->company_code = env('boc_common.company_code'); $this->boc_sm2_public_key = env('boc_common.boc_sm2_public_key'); $this->gz_sm2_public_key = env('boc_common.gz_sm2_public_key'); $this->gz_sm2_private_key = env('boc_common.gz_sm2_private_key'); $this->sm2 = new RtSm2(); $adapter = RtEccFactory::getAdapter(); $this->plain_boc_sm2_public_key = $this->getPublicKeyPlainText($adapter, $this->boc_sm2_public_key); $this->plain_gz_sm2_public_key = $this->getPublicKeyPlainText($adapter, $this->gz_sm2_public_key); $this->plain_gz_sm2_private_key = $this->getPrivateKeyPlainText($this->gz_sm2_private_key); } public function getPrivateKeyPlainText($base64_private_key) { $private_key_decoded = base64_decode($base64_private_key); $private_key_hex = bin2hex($private_key_decoded); $private_key_start = strpos($private_key_hex, '0420'); if ($private_key_start !== false) { return substr($private_key_hex, $private_key_start + 4, 64); } return ''; } public function getPublicKeyPlainText($adapter, $base64_public_key) { // 为 Base64 密钥添加 PEM 格式头和尾 $public_key_pem = "-----BEGIN PUBLIC KEY-----\n" . chunk_split($base64_public_key, 64, "\n") . "-----END PUBLIC KEY-----\n"; $pemPublicSerializer = new PemPublicKeySerializer(new DerPublicKeySerializer($adapter)); $publicKeyObject = $pemPublicSerializer->parse($public_key_pem); $pubPoint = $publicKeyObject->getPoint(); $pubX = $this->sm2->decHex($pubPoint->getX()); $pubY = $this->sm2->decHex($pubPoint->getY()); return '04' . $pubX . $pubY; } public function verifySign($cipher_key, $cipher_text, $sign) { $sm4_key = $this->sm2->doDecrypt($cipher_key, $this->plain_gz_sm2_private_key); $sm4 = new MySm4($sm4_key); $plain_text = $sm4->decrypt($cipher_text); $verify_res = $this->sm2->verifySign($plain_text, $sign, $this->plain_boc_sm2_public_key); if ($verify_res) { $this->plain_text = $plain_text; } return $verify_res; } public function getPlainText() { return $this->plain_text; } public function encryptData($data) { Log::error("----encryptData----"); $data_str = json_encode($data, JSON_UNESCAPED_UNICODE); Log::error("----data_str----"); Log::error($data_str); $sign = $this->sm2->doSign($data_str, $this->plain_gz_sm2_private_key); Log::error("----sign----"); Log::error($sign); $sm4Key = HexUtil::encodeHexStr(BocCipherUtil::generateKey()); Log::error("----sm4_key----"); Log::error($sm4Key); $sm4 = new MySm4($sm4Key); $cipher_text = $sm4->encrypt($data_str); Log::error("----cipher_text----"); Log::error(strlen($cipher_text)); $cipher_key = '04' . strtoupper($this->sm2->doEncrypt($sm4Key, $this->plain_boc_sm2_public_key)); Log::error("----cipher_key----"); Log::error($cipher_key); Log::error("----encryptData----"); return [ 'cipherkey' => $cipher_key, 'ciphertext' => $cipher_text, 'sign' => $sign, 'plain_text' => $data_str, ]; } public function decryptData($result_data) { Log::error("----decryptData----"); $sm4_key = $this->sm2->doDecrypt($result_data['cipherkey'], $this->plain_gz_sm2_private_key); Log::error("----sm4_key----"); Log::error($sm4_key); $sm4 = new MySm4($sm4_key); $plain_text = $sm4->decrypt($result_data['ciphertext']); Log::error("----plain_text----"); Log::error($plain_text); Log::error("----decryptData----"); return json_decode($plain_text, true); } /** * 组装发送给中行的返回数据(用于返回客户端) * @param $code string 响应码 0=成功 * @param $message string 响应消息 * @parma $other_response_biz_content array 其他业务响应参数 * @param $req_date array 请求参数 * @return \think\response */ public function buildResponseData( string $code, string $message, array $req_data ) { // 业务响应参数 $response_content = [ 'code' => $code, 'message' => $message, 'data' => null, ]; $resp_data = $this->encryptData($response_content); if (!empty($resp_data) && !empty($req_data)) { $insert_boc_req_resp = [ 'direct' => 2, 'req_cipher_key' => $req_data['cipherkey'] ?? '', 'req_cipher_text' => $req_data['ciphertext'] ?? '', 'req_sign' => $req_data['sign'], 'req_plain_text' => $this->plain_text, 'resp_cipher_key' => $resp_data['cipherkey'], 'resp_cipher_text' => $resp_data['ciphertext'], 'resp_sign' => $resp_data['sign'], 'resp_plain_text' => $resp_data['plain_text'], 'create_time' => date('Y-m-d H:i:s'), 'update_time' => date('Y-m-d H:i:s'), ]; Db::name('boc_req_resp')->insert($insert_boc_req_resp); } unset($resp_data['plain_text']); $resp_data['companyCode'] = $this->company_code; $headers['content-type'] = 'application/json'; return Response::create(json_encode($resp_data, 256), '', 200, $headers); } private function getInquiryInfo($quot_id) { $this->inquiry_info = Db::name('inquiry')->where('id', $quot_id)->find(); if (empty($this->inquiry_info)) { Log::error("询价单不存在"); Log::error("quot_id:{$quot_id}"); return '询价单不存在'; } return true; } private function getPropertyCertInfo($quot_id) { $this->property_cert_info = Db::name('property_cert_info')->where('quot_id', $quot_id)->select(); if (empty($this->property_cert_info)) { Log::error("物业信息不存在"); Log::error("quot_id:{$quot_id}"); return '物业信息不存在'; } return true; } private function getSurveyInfo($property_cert_info_ids) { $this->survey_info = Db::name('survey')->where('property_cert_info_id', 'in', $property_cert_info_ids)->select(); return true; } private function getReportInfo($quot_id) { $this->report_info = Db::name('report') ->where('quot_id', $quot_id) ->find(); if (empty($this->report_info)) { Log::error("报告单不存在"); return '报告单不存在'; } $this->report_detail_list = Db::name('report_detail') ->where('report_id', $this->report_info['id']) ->column('*', 'property_cert_info_id'); if (empty($this->report_detail_list)) { Log::error("报告单详情不存在"); return '报告单详情不存在'; } return true; } private function getCommonMain($quot_id) { $this->common_main_info = Db::name('boc_common_main') ->where('quot_id', $quot_id) ->find(); if (empty($this->common_main_info)) { Log::error("中行发起的记录不存在"); return '中行发起的记录不存在'; } return true; } private function getPreApplyInfo($boc_common_id) { $this->preapply_info = Db::name('boc_common_preapply') ->where('boc_common_id', $boc_common_id) ->find(); if (empty($this->preapply_info)) { Log::error("中行发起的预评估记录不存在"); return '中行发起的预评估记录不存在'; } return true; } private function getApplyOfficialInfo($bank_estimate_no) { $this->apply_official_info = Db::name('boc_common_apply_official') ->where('bankEstimateNo', $bank_estimate_no) ->find(); if (empty($this->apply_official_info)) { Log::error("中行发起的正式评估记录不存在"); return '中行发起的正式评估记录不存在'; } return true; } private function getApplyOfficialPreEstimateList($boc_common_apply_official_id) { $list = Db::name('boc_common_apply_official_pre_estimate') ->where('boc_common_apply_official_id', $boc_common_apply_official_id) ->select(); $this->apply_official_pre_estimate_list = Db::name('boc_common_preapply') ->where('bankPreEstimateNo', 'in', array_column($list, 'preEstimateNo')) ->select(); if (empty($this->apply_official_pre_estimate_list)) { Log::error("中行发起的预评估记录不存在"); return '中行发起的预评估记录不存在'; } return true; } public function savePreApply($data) { try { Db::startTrans(); $boc_common_id = Db::name('boc_common_main')->insertGetId([ 'bankPreEstimateNo' => $data['bankPreEstimateNo'], 'create_time' => date('Y-m-d H:i:s'), 'update_time' => date('Y-m-d H:i:s'), ]); if ($boc_common_id === false) { Db::rollback(); return '保存预评估数据失败'; } $boc_common_preapply_id = Db::name('boc_common_preapply')->insertGetId([ 'boc_common_id' => $boc_common_id, 'bankPreEstimateNo' => $data['bankPreEstimateNo'], 'bankerName' => $data['bankerName'], 'bankerPhone' => $data['bankerPhone'], 'estimateType' => $data['estimateType'] ?? '', 'propertyName' => $data['propertyName'] ?? '', 'channelCode' => $data['channelCode'], 'timestamp' => $data['timestamp'], 'companyCode' => $data['companyCode'], 'create_time' => date('Y-m-d H:i:s'), 'update_time' => date('Y-m-d H:i:s'), ]); if ($boc_common_preapply_id === false) { Db::rollback(); return '保存预评估数据失败'; } $propertyCard = json_decode($data['propertyCard'], true); $propertyCardType = json_decode($data['propertyCardType'], true); if (count($propertyCard) != count($propertyCardType)) { Db::rollback(); return '产权证数量和产权证文件格式的数量不一致'; } $boc_common_preapply_property_card_inst_data = []; $oss_service = new OssService(); $mime_types = [ 'jpg' => 'image/jpg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif', 'pdf' => 'application/pdf', ]; foreach ($propertyCard as $k => $v) { $url = ''; $mime_type = ''; foreach ($mime_types as $ext => $mime_type) { if ($ext == $propertyCardType[$k]) { $temp_file = str_replace('\\', '/', tempnam(sys_get_temp_dir(), 'cos_')); file_put_contents($temp_file, base64_decode($v)); $ossPath = '/uploads' . '/' . date('Ymd') . '/' . $data['bankPreEstimateNo'] . '-' . ($k + 1) . '.' . $ext; $url = $oss_service->uploadSingleFile($ossPath, $temp_file, $mime_type); if (file_exists($temp_file)) { unlink($temp_file); } break; } } $boc_common_preapply_property_card_inst_data[] = [ 'boc_common_id' => $boc_common_id, 'boc_common_preapply_id' => $boc_common_preapply_id, 'propertyCard' => "data:{$mime_type};base64," . $v, 'propertyCardType' => $propertyCardType[$k], 'propertyCardFileUrl' => str_replace('\\', '/', $url), 'create_time' => date('Y-m-d H:i:s'), 'update_time' => date('Y-m-d H:i:s'), ]; } if (!empty($boc_common_preapply_property_card_inst_data)) { $res = Db::name('boc_common_preapply_property_card')->insertAll($boc_common_preapply_property_card_inst_data); if ($res === false) { Db::rollback(); return '保存预评估数据失败'; } } Db::commit(); } catch (\Exception $e) { Db::rollback(); Log::error('错误文件:' . $e->getFile()); Log::error('错误行数:' . $e->getLine()); Log::error('错误编码:' . $e->getCode()); Log::error('错误信息:' . $e->getMessage()); return '保存预评估数据失败'; } return true; } public function saveApplyOfficial($data) { try { Db::startTrans(); $boc_common_insert_data = []; if (strtoupper($data['channelCode']) == 'XJ') { if (!empty($data['preEstimateNoList']) && count($data['preEstimateNoList']) == 1) { $boc_common_insert_data['is_related'] = 2; //自动关联上 $inquiry_info = Db::name('inquiry')->where('estimated_no', $data['preEstimateNoList'][0])->order('id desc')->find(); if (!empty($inquiry_info)) { $boc_common_insert_data['quot_id'] = $inquiry_info['id']; $boc_common_insert_data['order_no'] = $inquiry_info['order_no']; } } } $boc_common_insert_data['bankEstimateNo'] = $data['bankEstimateNo']; $boc_common_id = Db::name('boc_common_main')->insertGetId($boc_common_insert_data); if ($boc_common_id === false) { Db::rollback(); return '保存正式评估数据失败'; } $boc_common_apply_official_id = Db::name('boc_common_apply_official')->insertGetId([ 'boc_common_id' => $boc_common_id, 'bankEstimateNo' => $data['bankEstimateNo'], 'preEstimateNoList' => $data['preEstimateNoList'], 'timestamp' => $data['timestamp'], 'reportType' => $data['reportType'], 'companyCode' => $data['companyCode'], 'channelCode' => $data['channelCode'], 'create_time' => date('Y-m-d H:i:s'), 'update_time' => date('Y-m-d H:i:s'), ]); if ($boc_common_apply_official_id === false) { Db::rollback(); return '保存正式评估数据失败'; } $boc_common_apply_official_pre_estimate_data = []; foreach ($data['preEstimateNoList'] as $k => $v) { $boc_common_apply_official_pre_estimate_data[] = [ 'boc_common_id' => $boc_common_id, 'boc_common_apply_official_id' => $boc_common_apply_official_id, 'bankEstimateNo' => $data['bankEstimateNo'], 'preEstimateNo' => $v, 'create_time' => date('Y-m-d H:i:s'), 'update_time' => date('Y-m-d H:i:s'), ]; } if (!empty($boc_common_apply_official_pre_estimate_data)) { $res = Db::name('boc_common_apply_official_pre_estimate')->insertAll($boc_common_apply_official_pre_estimate_data); if ($res === false) { Db::rollback(); return '保存正式评估预评估数据失败'; } } 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; } public function sendPreResult($quot_id) { // 获取询价单信息 if (($res = $this->getInquiryInfo($quot_id)) !== true) { return $res; } if ($this->inquiry_info['status'] == 1) { return '询价单未回价'; } if (empty($this->inquiry_info['business_no'])) { Log::error("询价单业务编号为空"); Log::error("quot_id:{$quot_id}"); return '询价单业务编号为空'; } if (empty($this->inquiry_info['estimate_url'])) { return '预估单未上传'; } // 获取物业信息 if (($res = $this->getPropertyCertInfo($quot_id)) !== true) { return $res; } // 获取查勘信息 $this->getSurveyInfo(array_column($this->property_cert_info, 'id')); if (($res = $this->getCommonMain($quot_id)) !== true) { return $res; } // 获取中行发起的预评估记录 if (($res = $this->getPreApplyInfo($this->common_main_info['id'])) !== true) { return $res; } $plain_data = [ 'bankPreEstimateNo' => $this->preapply_info['bankPreEstimateNo'], 'preEstimateNo' => $this->inquiry_info['estimated_no'], 'estimateNo' => $this->inquiry_info['estimated_no'], 'roomArea' => $this->property_cert_info[0]['size'], 'unitPrice' => $this->property_cert_info[0]['eva_unit_price'], 'totalPrice' => $this->property_cert_info[0]['eva_total_value'], 'averagePrice' => 0, 'name' => $this->property_cert_info[0]['appraiser_name'], 'tax' => $this->property_cert_info[0]['total_taxes1'], 'finishedDate' => date('Ymd', strtotime($this->property_cert_info[0]['completion_time'])), 'ownerName' => $this->property_cert_info[0]['owner_name'], 'propertyName' => $this->property_cert_info[0]['land_location'] . $this->property_cert_info[0]['property_full_name'], 'cityName' => $this->property_cert_info[0]['city'], 'districtName' => $this->survey_info ? $this->survey_info[0]['area'] : '暂无信息', 'projectName' => $this->property_cert_info[0]['property_full_name'], 'propertyUse' => getDictionaryName('HOUSE_USAGE', $this->property_cert_info[0]['usage']), 'price1' => $this->property_cert_info[0]['eva_net_value'], 'price2' => $this->property_cert_info[0]['eva_net_value2'], 'price' => $this->property_cert_info[0]['eva_net_value2'], 'appraisedNetValue' => $this->property_cert_info[0]['eva_net_value2'] - $this->property_cert_info[0]['statutory_payment'], 'status' => '03', 'fileContent' => '', 'fileName' => basename(parse_url(str_replace('\\', '/', $this->inquiry_info['estimate_url']), PHP_URL_PATH)), 'fileIndex' => base64_encode(file_get_contents($this->inquiry_info['estimate_url'])), 'coveredArea' => 0, 'evalTime' => date('Ymd', $this->property_cert_info[0]['r_create_time']), 'telephoneNumber' => '', 'regPrice' => $this->property_cert_info[0]['reg_price'], 'landNo' => '', 'landLimitDate' => '', 'landBgnDate' => '', 'landEndDate' => '', 'houseProperty' => getDictionaryName('USE_RIGHT_SOURCE', $this->property_cert_info[0]['use_right_source']), 'registDate' => date('Ymd', strtotime($this->property_cert_info[0]['purchase_date'])), 'timestamp' => (int)round(microtime(true) * 1000), 'companyCode' => $this->preapply_info['companyCode'], 'intentReportType' => '01', 'channelCode' => $this->preapply_info['channelCode'], 'referencePrice' => $this->property_cert_info[0]['reference_price'] ?? 0, 'transactionTotalPrice' => $this->property_cert_info[0]['transaction_total_price'] ?? 0, 'transactionGrossArea' => $this->property_cert_info[0]['transaction_gross_area'] ?? 0, 'transactionDate' => $this->property_cert_info[0]['transaction_date'] ? date('Ymd', strtotime($this->property_cert_info[0]['transaction_date'])) : '', ]; $return_price = Db::name('return_price')->where('property_cert_info_id', $this->property_cert_info[0]['id'])->order('id desc')->find(); $tax_detail = []; if (!empty($return_price)) { $tax_detail[] = [ 'TaxName' => '增值税', 'TaxValue' => $return_price['added_tax'], ]; $tax_detail[] = [ 'TaxName' => '城建税', 'TaxValue' => $return_price['urban_construction_tax'], ]; $tax_detail[] = [ 'TaxName' => '教育附加费', 'TaxValue' => $return_price['edu_surcharge'], ]; $tax_detail[] = [ 'TaxName' => '土地增值税', 'TaxValue' => $return_price['land_value_added_tax'], ]; $tax_detail[] = [ 'TaxName' => '印花税', 'TaxValue' => $return_price['stamp_duty'], ]; $tax_detail[] = [ 'TaxName' => '个人所得税', 'TaxValue' => $return_price['personal_income_tax'], ]; $tax_detail[] = [ 'TaxName' => '契税', 'TaxValue' => $return_price['deed_tax'], ]; $tax_detail[] = [ 'TaxName' => '企业所得税', 'TaxValue' => $return_price['corporate_income_tax'], ]; $tax_detail[] = [ 'TaxName' => '拍卖费', 'TaxValue' => $return_price['auction_fee'], ]; $tax_detail[] = [ 'TaxName' => '交易服务费', 'TaxValue' => $return_price['tran_service_fee'], ]; } $plain_data['taxDetail'] = json_encode($tax_detail, JSON_UNESCAPED_UNICODE); $req_data = $this->encryptData($plain_data); unset($req_data['plain_text']); $req_data['companyCode'] = $this->company_code; Log::error('req_data:'); Log::error($req_data); $curl_result = curlRequest($this->base_url . $this->pre_result_uri, 'POST', $req_data, [ 'Content-Type: application/json', ], [], [], 0); Log::error('url:'); Log::error($this->base_url . $this->pre_result_uri); Log::error('curl_result:'); Log::error($curl_result); $result_string = $curl_result['data']; $result_data = json_decode($result_string, true); $validate = new CommonValidate(); if (!$validate->check($result_data)) { Log::error('validate error:'); Log::error($validate->getError()); return $validate->getError(); } if (!$this->verifySign($result_data['cipherkey'], $result_data['ciphertext'], $result_data['sign'])) { Log::error('verifySign error:'); Log::error('验签失败'); return '验签失败'; } $resp_data = $this->decryptData($result_data); if (isset($resp_data['code']) && $resp_data['code'] == 0) { return true; } return '发送预评估结果失败'; } public function sendApplyOfficialResult($quot_id) { // 获取询价单信息 if (($res = $this->getInquiryInfo($quot_id)) !== true) { return $res; } if ($this->inquiry_info['status'] != 8) { return '询价单未生成报告'; } if (($res = $this->getPropertyCertInfo($quot_id)) !== true) { return $res; } if (($res = $this->getReportInfo($this->inquiry_info['id'])) !== true) { return $res; } $preEstimateNo = ''; if (!empty($this->inquiry_info['business_no'])) { //线上 if ($this->inquiry_info['loan_type'] == '二手按揭') { // 消金 $this->apply_official_pre_estimate_list = Db::name('boc_common_preapply')->where('bankPreEstimateNo', $this->inquiry_info['business_no'])->select(); if (empty($this->apply_official_pre_estimate_list)) { return '预评估记录不存在'; } $bank_estimate_no = Db::name('boc_common_main') ->where('order_no', $this->inquiry_info['order_no']) ->where('bankEstimateNo IS NOT NULL AND bankEstimateNo != ""') ->value('bankEstimateNo'); $this->apply_official_info = Db::name('boc_common_apply_official') ->where('bankEstimateNo', $bank_estimate_no) ->find(); if (empty($this->apply_official_info)) { Log::error("中行发起的正式评估记录不存在"); return '中行发起的正式评估记录不存在'; } $preEstimateNo = json_decode($this->apply_official_info['preEstimateNoList'], true)[0]; } else { // todo 不会走到普惠,目前没有普惠业务,如果有普惠业务,这里需要修改这个 $this->apply_official_pre_estimate_list 2026-02-12 if (($res = $this->getApplyOfficialInfo($this->inquiry_info['business_no'])) !== true) { return $res; } if (($res = $this->getApplyOfficialPreEstimateList($this->apply_official_info['id'])) !== true) { return $res; } } $report_url = $this->report_info['report_url']; if (!empty($this->report_info['upload_report_url'])) { $report_url = $this->report_info['upload_report_url']; } $path = parse_url(str_replace('\\', '/', $report_url), PHP_URL_PATH); $bankerName = implode(',', array_column($this->apply_official_pre_estimate_list, 'bankerName')); $bankerPhone = implode(',', array_column($this->apply_official_pre_estimate_list, 'bankerPhone')); $base64 = $this->pdfToBase64($report_url); $plain_data = [ 'bankEstimateNo' => $this->apply_official_info['bankEstimateNo'], 'estimateNo' => $this->report_info['report_no'], 'fileIndex' => $base64, 'fileUrl' => $report_url, 'evalTime' => $this->report_info['appraisal_time'] ? date('Ymd', strtotime($this->report_info['appraisal_time'])) : date('Ymd'), 'name' => $this->report_info['appraiser_name'], 'companyCode' => $this->company_code, 'fileType' => '02', 'fileName' => basename($path), 'channelCode' => $this->apply_official_info['channelCode'], 'bankerName' => $bankerName, 'bankerPhone' => $bankerPhone, ]; foreach ($this->apply_official_pre_estimate_list as $item) { $preEstimatePropertyCertInfo = Db::name('property_cert_info')->alias('pci') ->field('pci.id, pci.land_location, pci.property_full_name, pci.city, pci.building_name, pci.usage, pci.cert_usage, pci.size, pci.eva_unit_price, pci.eva_total_value, pci.reg_price, pci.purchase_date, pci.completion_time, pci.eva_net_value, pci.eva_net_value2, pci.total_taxes1, pci.statutory_payment, pci.reference_price, pci.obligee, pci.transaction_total_price, pci.transaction_gross_area, pci.transaction_date') ->join('inquiry i', 'i.id = pci.quot_id') ->where('i.business_no', $item['bankPreEstimateNo']) // ->where("INSTR('{$item['propertyName']}', pci.property_full_name)") ->find(); if (empty($preEstimatePropertyCertInfo)) { continue; } $survey_info = Db::name('survey')->where('property_cert_info_id', $preEstimatePropertyCertInfo['id'])->find(); if (isset($this->report_detail_list[$preEstimatePropertyCertInfo['id']])) { $propertyStatus = 1; //默认,有效【中行中的枚举值:1有效 2抵押 3查封】 if ($this->report_detail_list[$preEstimatePropertyCertInfo['id']]['otherrights_type'] == 1) { //我方:已抵押未注销 $propertyStatus = 2; //抵押 } else if ($this->report_detail_list[$preEstimatePropertyCertInfo['id']]['otherrights_type'] == 2) { //我方:无抵押 $propertyStatus = 1; //有效 } else if ($this->report_detail_list[$preEstimatePropertyCertInfo['id']]['otherrights_type'] == 3) { //我方:查封 $propertyStatus = 3; //查封 } } $return_price = Db::name('return_price')->where('property_cert_info_id', $preEstimatePropertyCertInfo['id'])->order('id desc')->find(); $tax_detail = []; if (!empty($return_price)) { $tax_detail[] = [ 'TaxName' => '增值税', 'TaxValue' => $return_price['added_tax'], ]; $tax_detail[] = [ 'TaxName' => '城建税', 'TaxValue' => $return_price['urban_construction_tax'], ]; $tax_detail[] = [ 'TaxName' => '教育附加费', 'TaxValue' => $return_price['edu_surcharge'], ]; $tax_detail[] = [ 'TaxName' => '土地增值税', 'TaxValue' => $return_price['land_value_added_tax'], ]; $tax_detail[] = [ 'TaxName' => '印花税', 'TaxValue' => $return_price['stamp_duty'], ]; $tax_detail[] = [ 'TaxName' => '个人所得税', 'TaxValue' => $return_price['personal_income_tax'], ]; $tax_detail[] = [ 'TaxName' => '契税', 'TaxValue' => $return_price['deed_tax'], ]; $tax_detail[] = [ 'TaxName' => '企业所得税', 'TaxValue' => $return_price['corporate_income_tax'], ]; $tax_detail[] = [ 'TaxName' => '拍卖费', 'TaxValue' => $return_price['auction_fee'], ]; $tax_detail[] = [ 'TaxName' => '交易服务费', 'TaxValue' => $return_price['tran_service_fee'], ]; } $tmp = [ 'preEstimateNo' => $preEstimateNo, // todo 不会走到普惠,目前没有普惠业务,如果有普惠业务,这里需要修改这个 $this->apply_official_pre_estimate_list 2026-02-12 'propertyName' => $preEstimatePropertyCertInfo['land_location'] . $preEstimatePropertyCertInfo['property_full_name'] . $preEstimatePropertyCertInfo['city'], 'cityName' => $preEstimatePropertyCertInfo['city'], 'districtName' => $survey_info ? $survey_info['area'] : '暂无信息', 'projectName' => $preEstimatePropertyCertInfo['building_name'], 'propertyId' => isset($this->report_detail_list[$preEstimatePropertyCertInfo['id']]) ? $this->report_detail_list[$preEstimatePropertyCertInfo['id']]['property_cert'] : '', 'propertyUse' => getDictionaryName('HOUSE_USAGE', $preEstimatePropertyCertInfo['usage']), 'propertyUseRemark' => $preEstimatePropertyCertInfo['cert_usage'], 'landNo' => isset($this->report_detail_list[$preEstimatePropertyCertInfo['id']]) ? $this->report_detail_list[$preEstimatePropertyCertInfo['id']]['parcel_no'] : '', 'landLimitDate' => isset($this->report_detail_list[$preEstimatePropertyCertInfo['id']]) ? $this->report_detail_list[$preEstimatePropertyCertInfo['id']]['max_land_use_years'] : '', 'landBgnDate' => isset($this->report_detail_list[$preEstimatePropertyCertInfo['id']]) ? date('Ymd', strtotime($this->report_detail_list[$preEstimatePropertyCertInfo['id']]['land_use_start_time'])) : '', 'landEndDate' => isset($this->report_detail_list[$preEstimatePropertyCertInfo['id']]) ? date('Ymd', strtotime($this->report_detail_list[$preEstimatePropertyCertInfo['id']]['land_use_end_time'])) : '', 'finishedDate' => date('Ymd', strtotime($preEstimatePropertyCertInfo['completion_time'])), 'registPrice' => $preEstimatePropertyCertInfo['reg_price'], 'registDate' => date('Ymd', strtotime($preEstimatePropertyCertInfo['purchase_date'])), 'houseFlag' => $preEstimatePropertyCertInfo['usage'] == 1 ? '0' : '1', 'houseArea' => $preEstimatePropertyCertInfo['size'], 'houseCity' => $preEstimatePropertyCertInfo['city'], 'ownerName' => isset($this->report_detail_list[$preEstimatePropertyCertInfo['id']]) ? $this->report_detail_list[$preEstimatePropertyCertInfo['id']]['obligee'] : '', 'ownerCertId' => isset($this->report_detail_list[$preEstimatePropertyCertInfo['id']]) ? str_replace(["、", ","], ',', $this->report_detail_list[$preEstimatePropertyCertInfo['id']]['cert_no']) : '', 'ownerPortion' => isset($this->report_detail_list[$preEstimatePropertyCertInfo['id']]) ? (substr_count($this->report_detail_list[$preEstimatePropertyCertInfo['id']]['obligee_percent'], '%') == 1 ? '100%' : '') : '', 'mortName' => '', 'mortDate' => '', 'propertStatus' => $propertyStatus ?? '', 'sealupOrg' => '', 'sealupDate' => '', 'roomArea' => $preEstimatePropertyCertInfo['size'], 'unitPrice' => $preEstimatePropertyCertInfo['eva_unit_price'], 'totalPrice' => $preEstimatePropertyCertInfo['eva_total_value'], 'price1' => $preEstimatePropertyCertInfo['eva_net_value'], 'price2' => $preEstimatePropertyCertInfo['eva_net_value2'], 'price' => $preEstimatePropertyCertInfo['eva_net_value2'], 'appraisedNetValue' => $preEstimatePropertyCertInfo['eva_net_value2'] - $preEstimatePropertyCertInfo['statutory_payment'], 'tax' => $preEstimatePropertyCertInfo['total_taxes1'], 'referencePrice' => $preEstimatePropertyCertInfo['reference_price'] ?? 0, 'transactionTotalPrice' => $preEstimatePropertyCertInfo['transaction_total_price'] ?? 0, 'transactionGrossArea' => $preEstimatePropertyCertInfo['transaction_gross_area'] ?? 0, 'transactionDate' => $preEstimatePropertyCertInfo['transaction_date'] ? date('Ymd', strtotime($preEstimatePropertyCertInfo['transaction_date'])) : '', ]; $tmp['taxDetail'] = json_encode($tax_detail, 256); $plain_data['acOffHouseEstates'][] = $tmp; } } else { //线下 $report_url = $this->report_info['report_url']; if (!empty($this->report_info['upload_report_url'])) { $report_url = $this->report_info['upload_report_url']; } $path = parse_url(str_replace('\\', '/', $report_url), PHP_URL_PATH); $base64 = $this->pdfToBase64($report_url); $plain_data = [ 'estimateNo' => $this->report_info['report_no'], 'fileIndex' => $base64, 'fileUrl' => $report_url, 'evalTime' => $this->report_info['appraisal_time'] ? date('Ymd', strtotime($this->report_info['appraisal_time'])) : date('Ymd'), 'name' => $this->report_info['appraiser_name'], 'companyCode' => $this->company_code, 'fileType' => '02', 'fileName' => basename($path), 'channelCode' => 'XJ', 'bankerName' => $this->inquiry_info['bank_customer_mgr_name'], 'bankerPhone' => $this->inquiry_info['bank_customer_mgr_phone'], ]; foreach ($this->property_cert_info as $item) { $survey_info = Db::name('survey')->where('property_cert_info_id', $item['id'])->find(); if (isset($this->report_detail_list[$item['id']])) { $propertyStatus = 1; //默认,有效【中行中的枚举值:1有效 2抵押 3查封】 if ($this->report_detail_list[$item['id']]['otherrights_type'] == 1) { //我方:已抵押未注销 $propertyStatus = 2; //抵押 } else if ($this->report_detail_list[$item['id']]['otherrights_type'] == 2) { //我方:无抵押 $propertyStatus = 1; //有效 } else if ($this->report_detail_list[$item['id']]['otherrights_type'] == 3) { //我方:查封 $propertyStatus = 3; //查封 } } $return_price = Db::name('return_price')->where('property_cert_info_id', $item['id'])->order('id desc')->find(); $tax_detail = []; if (!empty($return_price)) { $tax_detail[] = [ 'TaxName' => '增值税', 'TaxValue' => $return_price['added_tax'], ]; $tax_detail[] = [ 'TaxName' => '城建税', 'TaxValue' => $return_price['urban_construction_tax'], ]; $tax_detail[] = [ 'TaxName' => '教育附加费', 'TaxValue' => $return_price['edu_surcharge'], ]; $tax_detail[] = [ 'TaxName' => '土地增值税', 'TaxValue' => $return_price['land_value_added_tax'], ]; $tax_detail[] = [ 'TaxName' => '印花税', 'TaxValue' => $return_price['stamp_duty'], ]; $tax_detail[] = [ 'TaxName' => '个人所得税', 'TaxValue' => $return_price['personal_income_tax'], ]; $tax_detail[] = [ 'TaxName' => '契税', 'TaxValue' => $return_price['deed_tax'], ]; $tax_detail[] = [ 'TaxName' => '企业所得税', 'TaxValue' => $return_price['corporate_income_tax'], ]; $tax_detail[] = [ 'TaxName' => '拍卖费', 'TaxValue' => $return_price['auction_fee'], ]; $tax_detail[] = [ 'TaxName' => '交易服务费', 'TaxValue' => $return_price['tran_service_fee'], ]; } $tmp = [ 'propertyName' => $item['land_location'] . $item['property_full_name'] . $item['city'], 'cityName' => $item['city'], 'districtName' => $survey_info ? $survey_info['area'] : '暂无信息', 'projectName' => $item['building_name'], 'propertyId' => isset($this->report_detail_list[$item['id']]) ? $this->report_detail_list[$item['id']]['property_cert'] : '', 'propertyUse' => getDictionaryName('HOUSE_USAGE', $item['usage']), 'propertyUseRemark' => $item['cert_usage'], 'landNo' => isset($this->report_detail_list[$item['id']]) ? $this->report_detail_list[$item['id']]['parcel_no'] : '', 'landLimitDate' => isset($this->report_detail_list[$item['id']]) ? $this->report_detail_list[$item['id']]['max_land_use_years'] : '', 'landBgnDate' => isset($this->report_detail_list[$item['id']]) ? date('Ymd', strtotime($this->report_detail_list[$item['id']]['land_use_start_time'])) : '', 'landEndDate' => isset($this->report_detail_list[$item['id']]) ? date('Ymd', strtotime($this->report_detail_list[$item['id']]['land_use_end_time'])) : '', 'finishedDate' => date('Ymd', strtotime($item['completion_time'])), 'registPrice' => $item['reg_price'], 'registDate' => date('Ymd', strtotime($item['purchase_date'])), 'houseFlag' => $item['usage'] == 1 ? '0' : '1', 'houseArea' => $item['size'], 'houseCity' => $item['city'], 'ownerName' => isset($this->report_detail_list[$item['id']]) ? $this->report_detail_list[$item['id']]['obligee_percent'] : '', 'ownerCertId' => isset($this->report_detail_list[$item['id']]) ? str_replace(["、", ","], ',', $this->report_detail_list[$item['id']]['cert_no']) : '', 'ownerPortion' => isset($this->report_detail_list[$item['id']]) ? (substr_count($this->report_detail_list[$item['id']]['obligee_percent'], '%') == 1 ? '100%' : '') : '', 'mortName' => '', 'mortDate' => '', 'propertStatus' => $propertyStatus ?? '', 'sealupOrg' => '', 'sealupDate' => '', 'roomArea' => $item['size'], 'unitPrice' => $item['eva_unit_price'], 'totalPrice' => $item['eva_total_value'], 'price1' => $item['eva_net_value'], 'price2' => $item['eva_net_value2'], 'price' => $item['eva_net_value2'], 'appraisedNetValue' => $item['eva_net_value2'] - $item['statutory_payment'], 'tax' => $item['total_taxes1'], 'referencePrice' => $item['reference_price'] ?? 0, 'transactionTotalPrice' => $item['transaction_total_price'] ?? 0, 'transactionGrossArea' => $item['transaction_gross_area'] ?? 0, 'transactionDate' => $item['transaction_date'] ? date('Ymd', strtotime($item['transaction_date'])) : '', ]; $tmp['taxDetail'] = json_encode($tax_detail, 256); $plain_data['acOffHouseEstates'][] = $tmp; } } $req_data = $this->encryptData($plain_data); unset($req_data['plain_text']); $req_data['companyCode'] = $this->company_code; $curl_result = curlRequest($this->base_url . $this->apply_official_result_uri, 'POST', $req_data, [ 'Content-Type: application/json', ], [], [], 0); Log::error('curl_result:'); Log::error($curl_result); $result_string = $curl_result['data']; $result_data = json_decode($result_string, true); $validate = new CommonValidate(); if (!$validate->check($result_data)) { Log::error('validate error:'); Log::error($validate->getError()); return $validate->getError(); } if (!$this->verifySign($result_data['cipherkey'], $result_data['ciphertext'], $result_data['sign'])) { Log::error('verifySign error:'); Log::error('验签失败'); return '验签失败'; } $resp_data = $this->decryptData($result_data); if (isset($resp_data['code']) && $resp_data['code'] == 0) { return true; } return '发送正式评估结果失败'; } public function pdfToBase64($url) { $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, // 设置为true,获取完整的响应数据 CURLOPT_FOLLOWLOCATION => true, CURLOPT_BINARYTRANSFER => true, // 关键二进制传输选项 CURLOPT_SSL_VERIFYPEER => false, // 生产环境需开启证书验证 CURLOPT_TIMEOUT => 60, // 增加超时时间 ]); // 执行curl请求,获取完整的PDF数据 $pdfData = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode !== 200 || empty($pdfData)) { throw new Exception("PDF获取失败,HTTP状态码:{$httpCode}"); } // 对完整的PDF数据进行base64编码 // 使用base64_encode函数,它会自动处理填充字符,确保只在末尾添加 $base64Buffer = base64_encode($pdfData); return $base64Buffer; } }