'', //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 $file_url * @return mixed */ function fileUploadUrl($file_url){ $config=$this->config; $file_name=CommonServer::creatServer()->getFileName($file_url); $filePath=public_path($file_url); $contentMd5=$this->contentMd5($filePath); $apiaddr="/v3/files/file-upload-url"; $requestType = HttpEmun::POST; $data=[ "contentMd5" =>$contentMd5, "contentType" =>"application/pdf", "convertToPDF" =>true, "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()); return $fileId; } /** * 获取文件状态 * @param $fileId * @return int|mixed */ function getFileStatus($fileId) { $config=$this->config; $apiaddr="/v3/files/{$fileId}"; $requestType = HttpEmun::GET; //生成签名验签+json体的header $signAndBuildSignAndJsonHeader = EsignHttpHelper::signAndBuildSignAndJsonHeader($config['eSignAppId'], $config['eSignAppSecret'], "", $requestType, $apiaddr); //发起接口请求 $response = EsignHttpHelper::doCommHttp($config['eSignHost'], $apiaddr, $requestType, $signAndBuildSignAndJsonHeader, ""); $ret=json_decode($response->getBody(),true); if(isset($ret['code']) && $ret['code']==0){ return $ret['data']['fileStatus']; }else{ return 0; } } /** * 获取签署文件对应关键字坐标 * @param $fileId * @param $keywords * @return array */ 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 setContractContract($sign_id,$fileId,$signJson,$file_name) { // $signJson = '[{"keyword":"fisher", "auth_type":"PSN", "id_no","AAAAA"}, {"keyword":"lily", "auth_type":"ORG", "id_no","AAAAA"}, {"keyword":"bob", "auth_type":"PSN", "id_no","AAAAA"}]'; $signData = json_decode($signJson,true); $keywords=[]; foreach ($signData as $k=>$v){ $keywords[]=$v['keyword']; } //获取对应关键字定位 //dd(111); $positionRet=ESignContractServer::creatServer()->getKeywordPositions($fileId,$keywords); if(empty($positionRet['code'])){ return ['code'=>0,'msg'=>'签署区域定位失败']; }else{ $positionData=$positionRet['data']; } $signers=[]; $signUrl = []; foreach ($signData as $value){ //对应关键字做xy坐标匹配 foreach ($positionData as $item){ if(count($item['positions'])<=0){ continue; } if($item['keyword']==$value['keyword']){ $position=end($item['positions']); $coordinate=end($position['coordinates']); $value['positionPage'] = $position['pageNum']; $value['positionX'] = $coordinate['positionX']; $value['positionY'] = $coordinate['positionY']; } } //签署方是机构还是个人 if ($value['auth_type'] == 'PSN'){ $member = Member::where('psnId',$value['id_no'])->first(); //记录需要手动签署的 $signUrl[]=[ 'promissoryName'=>$member['name'], 'psnAccount'=>$member['phone'], 'orgName'=>'', ]; //获取签章 $m_id = $member->{'id'}; // $seal=MemberSeal::where('m_id',$m_id)->where('seal_status',1)->select(['id','seal_id'])->first(); // //印章ID // $assignedSealId=$seal->{'seal_id'}; //组装信息 $signersData = [ "signerType" => 0, "psnSignerInfo" => [ "psnAccount" => $member->{'phone'}, 'psnInfo'=>[ 'psnName'=>$member->{'name'}, 'psnIDCardNum'=>$member->{'id_number'}, 'psnIDCardType'=>'CRED_PSN_CH_IDCARD', ], ], "signFields" =>[ [ "fileId" =>$fileId, "normalSignFieldConfig" => [ "autoSign" =>false, "signFieldStyle" =>1, // "assignedSealId"=>$assignedSealId, // 在signFields中设置 assignedSealId为授权企业印章id "signFieldPosition" => [ "positionPage" =>$value['positionPage'].'', "positionX" =>(int)$value['positionX'], "positionY" =>(int)$value['positionY'], ] ], "signDateConfig" => [ "dateFormat" => "yyyy-MM-dd" ], ] ], ]; }else{ $firm = Firm::where('orgId',$value['id_no'])->first(); //记录需要手动签署的 $signUrl[]=[ 'promissoryName'=>$firm['legal_name'], 'psnAccount'=>$firm['phone'], 'orgName'=>$firm['firm_name'], ]; //获取用户签章 $firm_id = $firm->{'id'}; // $seal=FirmSeal::where('firm_id',$firm_id)->where('seal_type','CONTRACT')->select(['id','seal_id'])->first(); // //印章ID // $assignedSealId=$seal->{'seal_id'}; $signersData = [ "signerType" => 1, "orgSignerInfo" => [ "orgName" => $firm->{'firm_name'}, 'orgInfo'=>[ 'orgIDCardNum'=>$firm->{'license_number'}, 'orgIDCardType'=>'CRED_ORG_USCC', ], "transactorInfo"=>[ "psnAccount"=>$firm['phone'], 'psnInfo'=>[ 'psnName'=>$firm['legal_name'], 'psnIDCardNum'=>$firm['legal_id_number'], 'psnIDCardType'=>'CRED_PSN_CH_IDCARD' ] ] ], "signFields" =>[ [ "fileId" =>$fileId, "normalSignFieldConfig" => [ "autoSign" =>false, "signFieldStyle" =>1, // "assignedSealId"=>$assignedSealId, // 在signFields中设置 assignedSealId为授权企业印章id "signFieldPosition" => [ "positionPage" =>$value['positionPage'].'', "positionX" =>(int)$value['positionX'], "positionY" =>(int)$value['positionY'], ] ], "signDateConfig" => [ "dateFormat" => "yyyy-MM-dd" ], ] ], ]; } $signers[]=$signersData; //对应签署方做记录 SignRecord::create([ 'sign_id' => $sign_id, 'authType' => $value['auth_type'], 'id_no' => $value['id_no'], 'keyword' => $value['keyword'], 'page_num' => $value['positionPage'], 'position_x' => $value['positionX'], 'position_y' => $value['positionY'], ]); } if(empty($signers)){ return ['code'=>0,'msg'=>'暂无可执行电签印章']; } $flowId= $this->createByFile($fileId,$file_name.'.pdf',$file_name,$signers); if($flowId){ SignContract::where('id',$sign_id)->update(['flow_id'=>$flowId,'status'=>1]); foreach ($signUrl as $item){ $urlRet= $this->getSignUrl($flowId,$item['psnAccount'],$item['orgName']); $parts = parse_url($urlRet); $path = trim($parts['path'],'/'); $zh_url = route('member.sign').'?'.$path; if($urlRet){ // $content='尊敬的'.$item['promissoryName'].',您有待签署合同《'.$file_name.'》,点击签署 '.$urlRet.'。拒收请回复R'; $zh_url=str_replace('esign.jhcs888.com','app.jhcs888.com',$zh_url); $content='尊敬的'.$item['promissoryName'].',您有待签署合同《'.$file_name.'》,点击签署 '.$zh_url.'。拒收请回复R'; SmsServer::creatServer()->sendContent($item['psnAccount'],$content); SignContract::where('id',$sign_id)->update(['sign_url'=>$urlRet]); } } return ['code'=>1,'msg'=>'发起签署成功']; }else{ return ['code'=>0,'msg'=>'发起签署失败']; } } /** * 合同签署 * @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('adminApi.notify.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; } /** * 合同签署链接 * @param $flowId * @param $psnAccount * @param $orgName * @return null */ 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; } function downloadFileUrl($flow_id) { $config=$this->config; $apiaddr="/v3/sign-flow/{$flow_id}/file-download-url"; $requestType = HttpEmun::GET; //生成签名验签+json体的header $signAndBuildSignAndJsonHeader = EsignHttpHelper::signAndBuildSignAndJsonHeader($config['eSignAppId'], $config['eSignAppSecret'], "", $requestType, $apiaddr); //发起接口请求 $response = EsignHttpHelper::doCommHttp($config['eSignHost'], $apiaddr, $requestType, $signAndBuildSignAndJsonHeader, ""); $ret=json_decode($response->getBody(),true); if(isset($ret['code']) && $ret['code']==0){ return $ret['data']; }else{ return 0; } } }