'', //app id 'eSignAppSecret'=>'', // app key 'eSignHost'=>'https://smlopenapi.esign.cn', //模拟环境 // 'url'=>'https://openapi.esign.cn' //正式环境 ]; function __construct() { $this->config['eSignAppId']=env('E_SIGN_APP_ID'); $this->config['eSignAppSecret']=env('E_SIGN_APP_SECRET'); $this->config['eSignPublicKey']=env('E_SIGN_PUBLIC_KEY'); $this->config['eSignHost']=env('E_SIGN_HOST'); } /** * 创建对象 * @return ESignContractServer */ static function creatServer() { if (empty(self::$server)) self::$server = new ESignContractServer(); return self::$server; } function contentMd5($filePath){ if(!file_exists($filePath)){ EsignLogHelper::printMsg($filePath."文件不存在");exit; } return EsignUtilHelper::getContentBase64Md5($filePath); } /** * 上传合同文件至E签宝 * @param FactoringContractFile $file * @return mixed */ function fileUploadUrl(FactoringContractFile $file){ $config=$this->config; $file_pdf=$file->{'file_pdf'}; $app_url=env('APP_URL'); $file_pdf=str_replace($app_url,'',$file_pdf); $file_name=CommonServer::creatServer()->getFileName($file_pdf); $filePath=public_path($file_pdf); $contentMd5=$this->contentMd5($filePath); $apiaddr="/v3/files/file-upload-url"; $requestType = HttpEmun::POST; $data=[ "contentMd5" =>$contentMd5, "contentType" =>"application/pdf", "convertToPDF" =>false, "fileName" =>$file_name, "fileSize" =>filesize($filePath) ]; $paramStr = json_encode($data); //生成签名验签+json体的header $signAndBuildSignAndJsonHeader = EsignHttpHelper::signAndBuildSignAndJsonHeader($config['eSignAppId'], $config['eSignAppSecret'], $paramStr, $requestType, $apiaddr); //获取文件上传地址 EsignLogHelper::printMsg($signAndBuildSignAndJsonHeader); $response = EsignHttpHelper::doCommHttp($config['eSignHost'], $apiaddr, $requestType, $signAndBuildSignAndJsonHeader, $paramStr); EsignLogHelper::printMsg($response->getStatus()); EsignLogHelper::printMsg($response->getBody()); $fileUploadUrl=json_decode($response->getBody())->data->fileUploadUrl; $fileId=json_decode($response->getBody())->data->fileId; //文件流put上传 $response=EsignHttpHelper::upLoadFileHttp($fileUploadUrl,$filePath,"application/pdf"); EsignLogHelper::printMsg($response->getStatus()); EsignLogHelper::printMsg($response->getBody()); $file->update(['sign_file_id'=>$fileId]); return $fileId; } function getKeywordPositions($fileId,$keywords) { $config=$this->config; $apiaddr="/v3/files/{$fileId}/keyword-positions"; $requestType = HttpEmun::POST; $data=[ "keywords" =>$keywords ]; $paramStr = json_encode($data); //生成签名验签+json体的header $signAndBuildSignAndJsonHeader = EsignHttpHelper::signAndBuildSignAndJsonHeader($config['eSignAppId'], $config['eSignAppSecret'], $paramStr, $requestType, $apiaddr); //获取文件上传地址 EsignLogHelper::printMsg($signAndBuildSignAndJsonHeader); $response = EsignHttpHelper::doCommHttp($config['eSignHost'], $apiaddr, $requestType, $signAndBuildSignAndJsonHeader, $paramStr); EsignLogHelper::printMsg($response->getStatus()); EsignLogHelper::printMsg($response->getBody()); $ret=json_decode($response->getBody(),true); if(isset($ret['code']) && $ret['code']==0){ return ['code'=>'1','msg'=>'ok','data'=>$ret['data']['keywordPositions']]; }else{ return ['code'=>'0','msg'=>$ret['message']]; } } function getFileStatus($fileId) { $config=$this->config; $apiaddr="/v3/files/{$fileId}"; $requestType = HttpEmun::GET; //生成签名验签+json体的header $signAndBuildSignAndJsonHeader = EsignHttpHelper::signAndBuildSignAndJsonHeader($config['eSignAppId'], $config['eSignAppSecret'], "", $requestType, $apiaddr); //发起接口请求 // EsignLogHelper::printMsg($signAndBuildSignAndJsonHeader); $response = EsignHttpHelper::doCommHttp($config['eSignHost'], $apiaddr, $requestType, $signAndBuildSignAndJsonHeader, ""); // EsignLogHelper::printMsg($response->getStatus()); // EsignLogHelper::printMsg($response->getBody()); $ret=json_decode($response->getBody(),true); if(isset($ret['code']) && $ret['code']==0){ return ['code'=>'1','msg'=>'ok','data'=>$ret['data']]; }else{ return ['code'=>'0','msg'=>$ret['message']]; } } /** * 生成待电签记录 * @param $contractId * @return void */ function addSignContract($contractId) { $num=SignContract::where('contract_id',$contractId)->count(); if($num<=0){ SignContract::create(['contract_id'=>$contractId,'status' => 0,'file_id'=>'','msg'=>'']); } } function setContractContract() { $list=SignContract::where('status',0)->limit(10)->get(); foreach ($list as $k=>$v){ $contract=FactoringContract::where('id',$v->{'contract_id'})->select(['id','file_no','name','status','signatory','property','factoring_id','firm_id','factor_id'])->first(); if(empty($contract)){ $v->update(['status' => 3,'msg'=>'合同信息不存在']); }else{ $file=FactoringContractFile::where('file_no',$contract->{'file_no'})->where('type',2)->orderBy('id','desc')->select(['id','file_pdf','file_name','file_no','file_path','version'])->first(); if(empty($file)){ sleep(1); continue; } if(empty($v['file_id'])){ //上传E签宝文件模板 $fileId=$this->fileUploadUrl($file); if(empty($fileId)){ $v->update(['status' => 3,'msg'=>'合同模板上传失败']); }else{ $v->update(['file_id' => $fileId,'contract_file_id'=>$file['id']]); } $file->update(['sign_file_id'=>$fileId]); }else{ $fileId=$v['file_id']; } //校验盖章区域 $signatory=$contract->{'signatory'}; $keywords=[]; if(in_array(1,$signatory)){ $keywords[]=FactoringContractText::where('id',2)->value('custom'); } if(in_array(5,$signatory)){ $keywords[]=FactoringContractText::where('id',3)->value('custom'); } if(empty($keywords)){ $v->update(['status' => 3,'msg'=>'无需要电签']); continue; } $positionRet=ESignContractServer::creatServer()->getKeywordPositions($fileId,$keywords); if(empty($positionRet['code'])){ $v->update(['status' => 3,'msg'=>'签署区域定位失败']); continue; }else{ $positionData=$positionRet['data']; } $propertyIds=$contract->{'property'}; $propertyItem=FactoringProperty::whereIn('id',$propertyIds)->select(['id','firm_id','factor_id'])->first(); if(empty($propertyItem)){ $v->update(['status' => 3,'msg'=>'资产信息异常']); continue; } $signers=[]; $isAuto=1; $signUrl=[]; foreach ($positionData as $item){ if(count($item['positions'])<=0){ continue; } if($item['keyword']=='#转让方盖章处#'){ $signType=1; $firmId=$contract['firm_id']; }else{ $firmId=$contract['factor_id']; $signType=5; } $orgId=SignFirm::where('firm_id',$firmId)->value('org_id'); $seal=SignSeal::where('firm_id',$firmId)->where('seal_type','CONTRACT')->select(['id','seal_id','is_auth'])->first(); dump($seal); if(empty($orgId) || empty($seal)){ continue; } $assignedSealId=$seal->{'seal_id'}; $position=end($item['positions']); $coordinate=end($position['coordinates']); if($seal->{'is_auth'}){ $sysOrgId=CommonServer::creatServer()->getConfigValue('sys_org_id'); $signer=[ "orgSignerInfo" => [ "orgId" => $sysOrgId //其他企业自动签署,设置orgId平台方id ], "signFields" =>[ [ "fileId" =>$fileId, "normalSignFieldConfig" => [ "autoSign" =>true, "signFieldStyle" =>1, "assignedSealId"=>$assignedSealId, // 在signFields中设置 assignedSealId为授权企业印章id "signFieldPosition" => [ "positionPage" =>$position['pageNum'].'', "positionX" =>(int)$coordinate['positionX'], "positionY" =>(int)$coordinate['positionY'], ] ] ] ], "signerType" =>1 ]; }else{ $isAuto=0; $member=Member::where('firm_id',$firmId)->where('is_admin',1)->select(['id','phone','promissory_name','promissory_id_number'])->first(); if(empty($member)){ continue; } $firm=Firm::where('id',$firmId)->select(['id','firm_name','license_number'])->first(); if(empty($firm)){ continue; } $psnId=SignMember::where('m_id',$member->id)->value('psnId'); if(empty($psnId)){ continue; } //记录需要手动签署的 $signUrl[]=[ 'promissoryName'=>$member['promissory_name'], 'psnAccount'=>$member['phone'], 'orgName'=>$firm->{'firm_name'}, 'type'=>$signType, 'is_auto'=>0 ]; $signer=[ "orgSignerInfo" => [ "orgName" => $firm->{'firm_name'}, 'orgInfo'=>[ 'orgIDCardNum'=>$firm->{'license_number'}, 'orgIDCardType'=>'CRED_ORG_USCC', ], "transactorInfo"=>[ "psnAccount"=>$member['phone'], 'psnInfo'=>[ 'psnIDCardNum'=>$member['promissory_id_number'], 'psnIDCardType'=>'CRED_PSN_CH_IDCARD' ] ] ], "signFields" =>[ [ "fileId" =>$fileId, "normalSignFieldConfig" => [ "autoSign" =>false, "signFieldStyle" =>1, "assignedSealId"=>$assignedSealId, // 在signFields中设置 assignedSealId为授权企业印章id "signFieldPosition" => [ "positionPage" =>$position['pageNum'].'', "positionX" =>(int)$coordinate['positionX'], "positionY" =>(int)$coordinate['positionY'], ] ] ] ], "signerType" =>1 ]; } $signers[]=$signer; } if(empty($signers)){ $v->update(['status' => 3,'msg'=>'暂无可执行电签印章']); continue; } // dd($signers); $flowId= $this->createByFile($fileId,$contract['name'].'.pdf',$contract['name'],$signers); if($flowId){ $v->update(['status' => $isAuto==1?2:1,'flow_id'=>$flowId]); if($signUrl){ foreach ($signUrl as $item){ // if($item['is_auto']){ // FactoringContractSign::where('contract_id',$v['contract_id'])->where('signatory',$item['type'])->update(['sign_url'=>'','status' => 1]); // FinancingServer::creatServer()->signFinancingContract($v['factoring_id'],$v['id'],$item['type']); // }else{ // // } $urlRet= $this->getSignUrl($flowId,$item['psnAccount'],$item['orgName']); if($urlRet){ $content='尊敬的'.$item['promissoryName'].',您有待签署合同《'.$contract['name'].'》,点击签署 '.$urlRet; SmsServer::creatServer()->sendContent($item['psnAccount'],$content); FactoringContractSign::where('contract_id',$v['contract_id'])->where('signatory',$item['type'])->update(['sign_url'=>$urlRet]); } } }else{ // $this->downloadFile($flowId); ContractServer::creatServer()->setContractFile($flowId); } }else{ $v->update(['status' => 3,'msg'=>'合同生成失败']); } } } return $list->count(); } function getSignUrl($flowId,$psnAccount,$orgName){ EsignLogHelper::printMsg("**********获取合同文件签署链接开始**********"); $config=$this->config; $apiaddr="/v3/sign-flow/%s/sign-url"; $apiaddr = sprintf($apiaddr,$flowId); $requestType = HttpEmun::POST; $data = [ "signFlowId" =>$flowId, "clientType" =>"ALL", "needLogin" =>false, "operator" => [ "psnAccount" =>$psnAccount ], 'organization'=>[ 'orgName'=>$orgName ], "urlType" =>2 ]; $paramStr = json_encode($data); $signAndBuildSignAndJsonHeader = EsignHttpHelper::signAndBuildSignAndJsonHeader($config['eSignAppId'], $config['eSignAppSecret'], $paramStr, $requestType, $apiaddr); EsignLogHelper::printMsg($signAndBuildSignAndJsonHeader); $response = EsignHttpHelper::doCommHttp($config['eSignHost'], $apiaddr, $requestType, $signAndBuildSignAndJsonHeader, $paramStr); EsignLogHelper::printMsg($response->getStatus()); EsignLogHelper::printMsg($response->getBody()); $url= null; if($response->getStatus() == 200){ $url = json_decode($response->getBody())->data->shortUrl; EsignLogHelper::printMsg("获取合同文件签署链接调用成功,url: ".$url); }else{ EsignLogHelper::printMsg("获取合同文件签署链接接口调用失败,HTTP错误码".$response->getStatus()); } EsignLogHelper::printMsg("**********获取合同文件签署链接调用结束**********"); return $url; } /** * 合同签署 * @param $fileId * @return false */ function createByFile($fileId,$fileName,$signFlowTitle,$signers) { EsignLogHelper::printMsg("**********基于文件发起签署调用开始**********"); $config=$this->config; $apiaddr="/v3/sign-flow/create-by-file"; $requestType = HttpEmun::POST; $data = [ "docs" =>[ [ "fileId" =>$fileId, "fileName" =>$fileName ] ], "signFlowConfig" => [ "signFlowTitle" =>$signFlowTitle, "autoStart"=>true, "autoFinish"=>true, 'notifyUrl'=>route('wps.esignNotify') ], "signers"=>$signers ]; // dd($data); $paramStr = json_encode($data); $signAndBuildSignAndJsonHeader = EsignHttpHelper::signAndBuildSignAndJsonHeader($config['eSignAppId'], $config['eSignAppSecret'], $paramStr, $requestType, $apiaddr); EsignLogHelper::printMsg($signAndBuildSignAndJsonHeader); $response = EsignHttpHelper::doCommHttp($config['eSignHost'], $apiaddr, $requestType, $signAndBuildSignAndJsonHeader, $paramStr); EsignLogHelper::printMsg($response->getStatus()); EsignLogHelper::printMsg($response->getBody()); $signFlowId = false; if($response->getStatus() == 200){ $result = json_decode($response->getBody()); if($result->code==0){ $signFlowId = $result->data->signFlowId; EsignLogHelper::printMsg("基于文件发起签署接口调用成功,flowId: ".$signFlowId); }else{ EsignLogHelper::printMsg("基于文件发起签署接口调用失败,错误信息: ".$result->message); } }else{ EsignLogHelper::printMsg("基于文件发起签署接口调用失败,HTTP错误码".$response->getStatus()); } EsignLogHelper::printMsg("**********基于文件发起签署调用结束**********"); return $signFlowId; } function downloadFile($flowId){ $config=$this->config; EsignLogHelper::printMsg("**********下载已签署文件及附属材料开始**********"); $apiaddr="/v3/sign-flow/%s/file-download-url"; $apiaddr = sprintf($apiaddr,$flowId); $requestType = HttpEmun::GET; $paramStr = null; $signAndBuildSignAndJsonHeader = EsignHttpHelper::signAndBuildSignAndJsonHeader($config['eSignAppId'], $config['eSignAppSecret'], $paramStr, $requestType, $apiaddr); EsignLogHelper::printMsg($signAndBuildSignAndJsonHeader); $response = EsignHttpHelper::doCommHttp($config['eSignHost'], $apiaddr, $requestType, $signAndBuildSignAndJsonHeader, $paramStr); EsignLogHelper::printMsg($response->getStatus()); EsignLogHelper::printMsg($response->getBody()); if($response->getStatus() == 200){ EsignLogHelper::printMsg("下载已签署文件及附属材料调用成功: ".$response->getBody()); return json_decode($response->getBody(),true); }else{ EsignLogHelper::printMsg("下载已签署文件及附属材料调用失败,HTTP错误码".$response->getStatus()); } EsignLogHelper::printMsg("**********下载已签署文件及附属材料调用结束**********"); return false; } }