ESignContractServer.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. <?php
  2. namespace App\Servers\ESign;
  3. use App\Models\Firm;
  4. use App\Models\FirmSeal;
  5. use App\Models\Member;
  6. use App\Models\MemberSeal;
  7. use App\Models\SignContract;
  8. use App\Models\SignRecord;
  9. use App\Servers\ESign\comm\EsignHttpHelper;
  10. use App\Servers\ESign\comm\EsignLogHelper;
  11. use App\Servers\ESign\comm\EsignUtilHelper;
  12. use App\Servers\ESign\emun\HttpEmun;
  13. use App\Servers\System\CommonServer;
  14. use App\Servers\System\SmsServer;
  15. class ESignContractServer
  16. {
  17. static private $server = null;
  18. public $config = [
  19. 'eSignAppId'=>'', //app id
  20. 'eSignAppSecret'=>'', // app key
  21. 'eSignHost'=>'https://smlopenapi.esign.cn', //模拟环境
  22. // 'url'=>'https://openapi.esign.cn' //正式环境
  23. ];
  24. function __construct()
  25. {
  26. $this->config['eSignAppId']=env('E_SIGN_APP_ID');
  27. $this->config['eSignAppSecret']=env('E_SIGN_APP_SECRET');
  28. $this->config['eSignPublicKey']=env('E_SIGN_PUBLIC_KEY');
  29. $this->config['eSignHost']=env('E_SIGN_HOST');
  30. }
  31. /**
  32. * 创建对象
  33. * @return ESignContractServer
  34. */
  35. static function creatServer()
  36. {
  37. if (empty(self::$server)) self::$server = new ESignContractServer();
  38. return self::$server;
  39. }
  40. function contentMd5($filePath){
  41. if(!file_exists($filePath)){
  42. EsignLogHelper::printMsg($filePath."文件不存在");exit;
  43. }
  44. return EsignUtilHelper::getContentBase64Md5($filePath);
  45. }
  46. /**
  47. * 上传合同文件至E签宝
  48. * @param $file_url
  49. * @return mixed
  50. */
  51. function fileUploadUrl($file_url){
  52. $config=$this->config;
  53. $file_name=CommonServer::creatServer()->getFileName($file_url);
  54. $filePath=public_path($file_url);
  55. $contentMd5=$this->contentMd5($filePath);
  56. $apiaddr="/v3/files/file-upload-url";
  57. $requestType = HttpEmun::POST;
  58. $data=[
  59. "contentMd5" =>$contentMd5,
  60. "contentType" =>"application/pdf",
  61. "convertToPDF" =>true,
  62. "fileName" =>$file_name,
  63. "fileSize" =>filesize($filePath)
  64. ];
  65. $paramStr = json_encode($data);
  66. //生成签名验签+json体的header
  67. $signAndBuildSignAndJsonHeader = EsignHttpHelper::signAndBuildSignAndJsonHeader($config['eSignAppId'], $config['eSignAppSecret'], $paramStr, $requestType, $apiaddr);
  68. //获取文件上传地址
  69. EsignLogHelper::printMsg($signAndBuildSignAndJsonHeader);
  70. $response = EsignHttpHelper::doCommHttp($config['eSignHost'], $apiaddr, $requestType, $signAndBuildSignAndJsonHeader, $paramStr);
  71. EsignLogHelper::printMsg($response->getStatus());
  72. EsignLogHelper::printMsg($response->getBody());
  73. $fileUploadUrl=json_decode($response->getBody())->data->fileUploadUrl;
  74. $fileId=json_decode($response->getBody())->data->fileId;
  75. //文件流put上传
  76. $response=EsignHttpHelper::upLoadFileHttp($fileUploadUrl,$filePath,"application/pdf");
  77. EsignLogHelper::printMsg($response->getStatus());
  78. EsignLogHelper::printMsg($response->getBody());
  79. return $fileId;
  80. }
  81. /**
  82. * 获取签署文件对应关键字坐标
  83. * @param $fileId
  84. * @param $keywords
  85. * @return array
  86. */
  87. function getKeywordPositions($fileId,$keywords)
  88. {
  89. $config=$this->config;
  90. $apiaddr="/v3/files/{$fileId}/keyword-positions";
  91. $requestType = HttpEmun::POST;
  92. $data=[
  93. "keywords" =>$keywords
  94. ];
  95. $paramStr = json_encode($data);
  96. //生成签名验签+json体的header
  97. $signAndBuildSignAndJsonHeader = EsignHttpHelper::signAndBuildSignAndJsonHeader($config['eSignAppId'], $config['eSignAppSecret'], $paramStr, $requestType, $apiaddr);
  98. //获取文件上传地址
  99. EsignLogHelper::printMsg($signAndBuildSignAndJsonHeader);
  100. $response = EsignHttpHelper::doCommHttp($config['eSignHost'], $apiaddr, $requestType, $signAndBuildSignAndJsonHeader, $paramStr);
  101. EsignLogHelper::printMsg($response->getStatus());
  102. EsignLogHelper::printMsg($response->getBody());
  103. $ret=json_decode($response->getBody(),true);
  104. if(isset($ret['code']) && $ret['code']==0){
  105. return ['code'=>'1','msg'=>'ok','data'=>$ret['data']['keywordPositions']];
  106. }else{
  107. return ['code'=>'0','msg'=>$ret['message']];
  108. }
  109. }
  110. function setContractContract($sign_id,$fileId,$signJson,$file_name)
  111. {
  112. // $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"}]';
  113. $signData = json_decode($signJson,true);
  114. $keywords=[];
  115. foreach ($signData as $k=>$v){
  116. $keywords[]=$v['keyword'];
  117. }
  118. //获取对应关键字定位
  119. $positionRet=ESignContractServer::creatServer()->getKeywordPositions($fileId,$keywords);
  120. if(empty($positionRet['code'])){
  121. return ['code'=>0,'msg'=>'签署区域定位失败'];
  122. }else{
  123. $positionData=$positionRet['data'];
  124. }
  125. $signers=[];
  126. foreach ($signData as $value){
  127. //对应关键字做xy坐标匹配
  128. foreach ($positionData as $item){
  129. if(count($item['positions'])<=0){
  130. continue;
  131. }
  132. if($item['keyword']==$value['keyword']){
  133. $position=end($item['positions']);
  134. $coordinate=end($position['coordinates']);
  135. $value['positionPage'] = $position['pageNum'];
  136. $value['positionX'] = $coordinate['positionX'];
  137. $value['positionY'] = $coordinate['positionY'];
  138. }
  139. }
  140. $signersData = [];
  141. //签署方是机构还是个人
  142. if ($value['auth_type'] == 'PSN'){
  143. $signerType = 0;
  144. $member = Member::where('psnId',$value['id_no'])->first();
  145. //获取企业签章
  146. $m_id = $member->{'id'};
  147. $seal=MemberSeal::where('m_id',$m_id)->select(['id','seal_id'])->first();
  148. //组装信息
  149. $signersData[] = [
  150. "psnSignerInfo" => [
  151. "psnAccount" => $member->{'phone'},
  152. 'psnInfo'=>[
  153. 'psnName'=>$member->{'name'},
  154. 'psnIDCardNum'=>$member->{'id_number'},
  155. 'psnIDCardType'=>'CRED_PSN_CH_IDCARD',
  156. ],
  157. ],
  158. ];
  159. }else{
  160. $signerType = 1;
  161. $firm = Firm::where('orgId',$value['id_no'])-first();
  162. //获取用户签章
  163. $firm_id = $firm->{'id'};
  164. $seal=FirmSeal::where('firm_id',$firm_id)->where('seal_type','CONTRACT')->select(['id','seal_id'])->first();
  165. $signersData[] = [
  166. "orgSignerInfo" => [
  167. "orgName" => $firm->{'firm_name'},
  168. 'orgInfo'=>[
  169. 'orgIDCardNum'=>$firm->{'license_number'},
  170. 'orgIDCardType'=>'CRED_ORG_USCC',
  171. ],
  172. "transactorInfo"=>[
  173. "psnAccount"=>$firm['phone'],
  174. 'psnInfo'=>[
  175. 'psnIDCardNum'=>$firm['legal_id_number'],
  176. 'psnIDCardType'=>'CRED_PSN_CH_IDCARD'
  177. ]
  178. ]
  179. ],
  180. ];
  181. }
  182. //印章ID
  183. $assignedSealId=$seal->{'seal_id'};
  184. $signersData[] = [
  185. "signFields" =>[
  186. [
  187. "fileId" =>$fileId,
  188. "normalSignFieldConfig" => [
  189. "autoSign" =>false,
  190. "signFieldStyle" =>1,
  191. "assignedSealId"=>$assignedSealId, // 在signFields中设置 assignedSealId为授权企业印章id
  192. "signFieldPosition" => [
  193. "positionPage" =>$value['pageNum'].'',
  194. "positionX" =>(int)$value['positionX'],
  195. "positionY" =>(int)$value['positionY'],
  196. ]
  197. ]
  198. ]
  199. ],
  200. "signerType" =>$signerType
  201. ];
  202. $signers[]=$signersData;
  203. //对应签署方做记录
  204. SignRecord::create([
  205. 'sign_id' => $sign_id,
  206. 'authType' => $value['auth_type'],
  207. 'id_no' => $value['id_no'],
  208. 'keyword' => $value['keyword'],
  209. 'page_num' => $value['pageNum'],
  210. 'position_x' => $value['positionX'],
  211. 'position_y' => $value['positionY'],
  212. ]);
  213. }
  214. if(empty($signers)){
  215. return ['code'=>0,'msg'=>'暂无可执行电签印章'];
  216. }
  217. $flowId= $this->createByFile($fileId,$file_name.'.pdf',$file_name,$signers);
  218. if($flowId){
  219. SignContract::where('id',$sign_id)->update(['flow_id'=>$flowId]);
  220. return ['code'=>1,'msg'=>'发起签署成功'];
  221. }else{
  222. return ['code'=>0,'msg'=>'发起签署失败'];
  223. }
  224. }
  225. /**
  226. * 合同签署
  227. * @param $fileId
  228. * @return false
  229. */
  230. function createByFile($fileId,$fileName,$signFlowTitle,$signers)
  231. {
  232. EsignLogHelper::printMsg("**********基于文件发起签署调用开始**********");
  233. $config=$this->config;
  234. $apiaddr="/v3/sign-flow/create-by-file";
  235. $requestType = HttpEmun::POST;
  236. $data = [
  237. "docs" =>[
  238. [
  239. "fileId" =>$fileId,
  240. "fileName" =>$fileName
  241. ]
  242. ],
  243. "signFlowConfig" => [
  244. "signFlowTitle" =>$signFlowTitle,
  245. "autoStart"=>true,
  246. "autoFinish"=>true,
  247. 'notifyUrl'=>route('notify.esignNotify')
  248. ],
  249. "signers"=>$signers
  250. ];
  251. // dd($data);
  252. $paramStr = json_encode($data);
  253. $signAndBuildSignAndJsonHeader = EsignHttpHelper::signAndBuildSignAndJsonHeader($config['eSignAppId'], $config['eSignAppSecret'], $paramStr, $requestType, $apiaddr);
  254. EsignLogHelper::printMsg($signAndBuildSignAndJsonHeader);
  255. $response = EsignHttpHelper::doCommHttp($config['eSignHost'], $apiaddr, $requestType, $signAndBuildSignAndJsonHeader, $paramStr);
  256. EsignLogHelper::printMsg($response->getStatus());
  257. EsignLogHelper::printMsg($response->getBody());
  258. $signFlowId = false;
  259. if($response->getStatus() == 200){
  260. $result = json_decode($response->getBody());
  261. if($result->code==0){
  262. $signFlowId = $result->data->signFlowId;
  263. EsignLogHelper::printMsg("基于文件发起签署接口调用成功,flowId: ".$signFlowId);
  264. }else{
  265. EsignLogHelper::printMsg("基于文件发起签署接口调用失败,错误信息: ".$result->message);
  266. }
  267. }else{
  268. EsignLogHelper::printMsg("基于文件发起签署接口调用失败,HTTP错误码".$response->getStatus());
  269. }
  270. EsignLogHelper::printMsg("**********基于文件发起签署调用结束**********");
  271. return $signFlowId;
  272. }
  273. }