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

1087 lines
46 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\BocCfValidate;
use app\lib\MySm4;
use app\model\BocCfInquiryApply;
use app\model\Inquiry;
use OneSm\Sm3;
use think\Db;
use think\facade\Log;
use think\facade\Response;
class BocCfService extends CommonService
{
// 交易代码
const EVA_REPORT_SUCCESS_PROVIDE = 'E001'; // 评估报告成功出具
const ESTIMATE_REPORT_SUCCESS_PROVIDE = 'E001'; // 询价单(预估报告)成功出具
const INQUIRY_APPLY = 'E002'; // 询价申请
const INQUIRY_RESULT_FEEDBACK = 'E003'; // 询价结果反馈
const APPLY_TO_PROVIDE_EVA_REPORT = 'E004'; // 申请出具评估报告
const ACCOUNT_MANAGER_INFO_SEARCH = 'E005'; // 客户经理信息查询
// 返回码
const RETURN_CODE_ARRAY = [
'0000' => '交易成功',
'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;
}
}