Files
pgserver3.0/pgserver/application/admin/service/BocCommonService.php
annnj-company 130c1026c4 first commit
2026-04-17 18:29:53 +08:00

969 lines
49 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace app\admin\service;
use app\common\validate\boc\CommonValidate;
use app\lib\BOC\BocCipherUtil;
use app\lib\HexUtil;
use app\lib\MySm4;
use Mdanter\Ecc\Serializer\PublicKey\DerPublicKeySerializer;
use Mdanter\Ecc\Serializer\PublicKey\PemPublicKeySerializer;
use Rtgm\ecc\RtEccFactory;
use Rtgm\sm\RtSm2;
use think\Db;
use think\facade\Log;
use think\facade\Response;
class BocCommonService extends CommonService
{
private $boc_sm2_public_key = ''; //中行公钥
private $gz_sm2_public_key = ''; //国中公钥
private $gz_sm2_private_key = ''; //国中私钥
private $plain_text = ''; //数据明文
private $plain_boc_sm2_public_key = '';
private $plain_sm2_private_key = '';
private $plain_gz_sm2_public_key = '';
// 银行接收预评估结果接口
private $pre_result_uri = '/cgs/pggsApi/estimate/receivePreResult/v3';
// 银行接收正式评估结果接口
private $apply_official_result_uri = '/cgs/pggsApi/estimate/receiveOff/v3';
private $base_url = '';
private $company_code = '';
private $inquiry_info = null;
private $property_cert_info = [];
private $survey_info = null;
private $latest_return_price_info = null;
private $report_info = null;
private $report_detail_list = [];
private $common_main_info = null;
private $preapply_info = null;
private $apply_official_info = null;
private $apply_official_pre_estimate_list = [];
private $sm2 = null;
public function __construct()
{
$this->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;
}
}