| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485 |
- <?php
- namespace App\Servers\ESign;
- use App\Models\FactoringContract;
- use App\Models\FactoringContractFile;
- use App\Models\FactoringContractSign;
- use App\Models\FactoringContractText;
- use App\Models\FactoringProperty;
- use App\Models\Firm;
- use App\Models\Member;
- use App\Models\SignContract;
- use App\Models\SignFirm;
- use App\Models\SignMember;
- use App\Models\SignSeal;
- use App\Servers\ESign\comm\EsignHttpHelper;
- use App\Servers\ESign\comm\EsignLogHelper;
- use App\Servers\ESign\comm\EsignUtilHelper;
- use App\Servers\ESign\emun\HttpEmun;
- use App\Servers\Financing\ContractServer;
- use App\Servers\Financing\FinancingServer;
- use App\Servers\System\CommonServer;
- use App\Servers\System\SmsServer;
- class ESignContractServer
- {
- static private $server = null;
- public $config = [
- 'eSignAppId'=>'', //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;
- }
- }
|