@ -8,12 +8,15 @@
package com.suisung.mall.shop.esign.service.impl ;
import cn.hutool.core.collection.CollectionUtil ;
import cn.hutool.core.util.ObjectUtil ;
import cn.hutool.core.util.StrUtil ;
import cn.hutool.json.JSONArray ;
import cn.hutool.json.JSONObject ;
import cn.hutool.json.JSONUtil ;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper ;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper ;
import com.suisung.mall.common.api.CommonResult ;
import com.suisung.mall.common.constant.CommonConstant ;
import com.suisung.mall.common.modules.esign.EsignContract ;
import com.suisung.mall.common.modules.esign.EsignContractFillingFile ;
@ -25,17 +28,30 @@ import com.suisung.mall.shop.esign.service.EsignContractFillingFileService;
import com.suisung.mall.shop.esign.service.EsignContractService ;
import com.suisung.mall.shop.esign.service.EsignPlatformInfoService ;
import com.suisung.mall.shop.esign.utils.comm.EsignHttpHelper ;
import com.suisung.mall.shop.esign.utils.comm.EsignHttpResponse ;
import com.suisung.mall.shop.esign.utils.enums.EsignRequestType ;
import com.suisung.mall.shop.esign.utils.exception.EsignDemoException ;
import com.suisung.mall.shop.page.service.OssService ;
import com.suisung.mall.shop.store.service.ShopMerchEntryService ;
import lombok.extern.slf4j.Slf4j ;
import org.springframework.beans.factory.annotation.Value ;
import org.springframework.context.annotation.Lazy ;
import org.springframework.http.HttpStatus ;
import org.springframework.http.ResponseEntity ;
import org.springframework.http.server.ServerHttpResponse ;
import org.springframework.stereotype.Service ;
import javax.annotation.Resource ;
import javax.crypto.Mac ;
import javax.crypto.spec.SecretKeySpec ;
import javax.servlet.http.HttpServletRequest ;
import java.io.UnsupportedEncodingException ;
import java.security.InvalidKeyException ;
import java.security.NoSuchAlgorithmException ;
import java.util.List ;
import java.util.Map ;
@Slf4j
@Service
public class EsignContractServiceImpl extends BaseServiceImpl < EsignContractMapper , EsignContract > implements EsignContractService {
@ -68,28 +84,177 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
@Resource
private EsignPlatformInfoService esignPlatformInfoService ;
/ / @Resource
/ / private EsignContractService esignContractService ;
@Resource
private OssService ossService ;
@Override
public Object signFlowCreateByFile ( ) {
String jsonParm = " { \" docs \" :[{ \" fileId \" : \" ab30d2c5600441f4a7daf512e4d69157 \" , \" fileName \" : \" 平台商户入驻合同协议.pdf \" }], \" signFlowConfig \" :{ \" signFlowTitle \" : \" 平台商户入驻合同协议 \" , \" signFlowExpireTime \" :1746844718000, \" autoFinish \" :true, \" notifyUrl \" : \" https://mall.gpxscs.cn/asyn/notify \" , \" redirectConfig \" :{ \" redirectUrl \" : \" https://mall.gpxscs.cn/ \" }}, \" signers \" :[{ \" signConfig \" :{ \" signOrder \" :1}, \" noticeConfig \" :{ \" noticeTypes \" : \" 1 \" }, \" signerType \" :0, \" psnSignerInfo \" :{ \" psnAccount \" : \" 13128997057 \" , \" psnInfo \" :{ \" psnName \" : \" 潘军杰 \" }}, \" signFields \" :[{ \" fileId \" : \" ab30d2c5600441f4a7daf512e4d69157 \" , \" normalSignFieldConfig \" :{ \" signFieldStyle \" :1, \" signFieldPosition \" :{ \" positionPage \" :40, \" positionX \" :472.3607, \" positionY \" :277.19104}}},{ \" fileId \" : \" ab30d2c5600441f4a7daf512e4d69157 \" , \" normalSignFieldConfig \" :{ \" signFieldStyle \" :1, \" signFieldPosition \" :{ \" positionPage \" :5, \" positionX \" :470.58798, \" positionY \" :589.14496}}}]},{ \" signConfig \" :{ \" signOrder \" :2}, \" noticeConfig \" :{ \" noticeTypes \" : \" 1 \" }, \" signerType \" :1, \" orgSignerInfo \" :{ \" orgName \" : \" 桂平发发网络有限公司 \" , \" orgInfo \" :{ \" orgIDCardNum \" : \" 91450881MADEQ92533 \" , \" orgIDCardType \" : \" CRED_ORG_USCC \" }, \" transactorInfo \" :{ \" psnAccount \" : \" 17777525395 \" , \" psnInfo \" :{ \" psnName \" : \" 谢能坤 \" }}}, \" signFields \" :[{ \" fileId \" : \" ab30d2c5600441f4a7daf512e4d69157 \" , \" normalSignFieldConfig \" :{ \" signFieldStyle \" :1, \" signFieldPosition \" :{ \" positionPage \" :2, \" positionX \" :479.04996, \" positionY \" :357.2327}}},{ \" fileId \" : \" ab30d2c5600441f4a7daf512e4d69157 \" , \" normalSignFieldConfig \" :{ \" signFieldStyle \" :1, \" signFieldPosition \" :{ \" positionPage \" :5, \" positionX \" :255.96832, \" positionY \" :588.4553}}}]}]} " ;
/ * * *
* 获取请求签名值
*
* @param data
* 加密前数据
* @param key
* 密钥
* @param algorithm
* HmacMD5 HmacSHA1 HmacSHA256 HmacSHA384 HmacSHA512
* @param encoding
* 编码格式
* @return HMAC加密后16进制字符串
* @throws Exception
* /
public static String getSignature ( String data , String key , String algorithm , String encoding ) {
Mac mac = null ;
try {
mac = Mac . getInstance ( algorithm ) ;
SecretKeySpec secretKey = new SecretKeySpec ( key . getBytes ( encoding ) , algorithm ) ;
mac . init ( secretKey ) ;
mac . update ( data . getBytes ( encoding ) ) ;
} catch ( NoSuchAlgorithmException e ) {
log . error ( " 获取Signature签名信息异常: {} " , e . getMessage ( ) ) ;
return null ;
} catch ( UnsupportedEncodingException e ) {
log . error ( " 获取Signature签名信息异常: {} " , e . getMessage ( ) ) ;
return null ;
} catch ( InvalidKeyException e ) {
log . error ( " 获取Signature签名信息异常: {} " , e . getMessage ( ) ) ;
return null ;
}
return byte2hex ( mac . doFinal ( ) ) ;
}
/ * * *
* 将byte [ ] 转成16进制字符串
*
* @param data
*
* @return 16进制字符串
* /
public static String byte2hex ( byte [ ] data ) {
StringBuilder hash = new StringBuilder ( ) ;
String stmp ;
for ( int n = 0 ; data ! = null & & n < data . length ; n + + ) {
stmp = Integer . toHexString ( data [ n ] & 0XFF ) ;
if ( stmp . length ( ) = = 1 )
hash . append ( '0' ) ;
hash . append ( stmp ) ;
}
return hash . toString ( ) ;
}
/ * *
* 基于文件发起签署电子合同
*
* @return
* /
@Override
public CommonResult signFlowCreateByFile ( String mchMobile ) {
if ( StrUtil . isBlank ( mchMobile ) ) {
return CommonResult . failed ( " 缺少必要参数! " ) ;
}
EsignContract esignContract = getEsignContractByMchMobile ( mchMobile ) ;
if ( esignContract = = null ) {
return CommonResult . failed ( " 未找到商家合同信息 " ) ;
}
/ / " { \" docs \" :[{ \" fileId \" : \" ab30d2c5600441f4a7daf512e4d69157 \" , \" fileName \" : \" 平台商户入驻合同协议.pdf \" }], \" signFlowConfig \" :{ \" signFlowTitle \" : \" 平台商户入驻合同协议 \" , \" signFlowExpireTime \" :1746844718000, \" autoFinish \" :true, \" notifyUrl \" : \" https://mall.gpxscs.cn/asyn/notify \" , \" redirectConfig \" :{ \" redirectUrl \" : \" https://mall.gpxscs.cn/ \" }}, \" signers \" :[{ \" signConfig \" :{ \" signOrder \" :1}, \" noticeConfig \" :{ \" noticeTypes \" : \" 1 \" }, \" signerType \" :0, \" psnSignerInfo \" :{ \" psnAccount \" : \" 13128997057 \" , \" psnInfo \" :{ \" psnName \" : \" 潘军杰 \" }}, \" signFields \" :[{ \" fileId \" : \" ab30d2c5600441f4a7daf512e4d69157 \" , \" normalSignFieldConfig \" :{ \" signFieldStyle \" :1, \" signFieldPosition \" :{ \" positionPage \" :40, \" positionX \" :472.3607, \" positionY \" :277.19104}}},{ \" fileId \" : \" ab30d2c5600441f4a7daf512e4d69157 \" , \" normalSignFieldConfig \" :{ \" signFieldStyle \" :1, \" signFieldPosition \" :{ \" positionPage \" :5, \" positionX \" :470.58798, \" positionY \" :589.14496}}}]},{ \" signConfig \" :{ \" signOrder \" :2}, \" noticeConfig \" :{ \" noticeTypes \" : \" 1 \" }, \" signerType \" :1, \" orgSignerInfo \" :{ \" orgName \" : \" 桂平发发网络有限公司 \" , \" orgInfo \" :{ \" orgIDCardNum \" : \" 91450881MADEQ92533 \" , \" orgIDCardType \" : \" CRED_ORG_USCC \" }, \" transactorInfo \" :{ \" psnAccount \" : \" 17777525395 \" , \" psnInfo \" :{ \" psnName \" : \" 谢能坤 \" }}}, \" signFields \" :[{ \" fileId \" : \" ab30d2c5600441f4a7daf512e4d69157 \" , \" normalSignFieldConfig \" :{ \" signFieldStyle \" :1, \" signFieldPosition \" :{ \" positionPage \" :2, \" positionX \" :479.04996, \" positionY \" :357.2327}}},{ \" fileId \" : \" ab30d2c5600441f4a7daf512e4d69157 \" , \" normalSignFieldConfig \" :{ \" signFieldStyle \" :1, \" signFieldPosition \" :{ \" positionPage \" :5, \" positionX \" :255.96832, \" positionY \" :588.4553}}}]}]} " ;
/ / esignContractService .
String jsonParams = esignContract . getReq_params ( ) ;
try {
/ / 请求方法
EsignRequestType requestType = EsignRequestType . POST ;
String apiaddr = " /v3/sign-flow/create-by-file " ;
Map < String , String > header = EsignHttpHelper . signAndBuildSignAndJsonHeader ( appId , appSecret , jsonParm , requestType . name ( ) , apiaddr , true ) ;
String api A ddr = " /v3/sign-flow/create-by-file " ;
Map < String , String > header = EsignHttpHelper . signAndBuildSignAndJsonHeader ( appId , appSecret , jsonPar a ms , requestType . name ( ) , api A ddr, true ) ;
/ / 发起接口请求
return EsignHttpHelper . doCommHttp ( serverUrl , apiaddr , requestType , jsonParm , header , debug ) ;
EsignHttpResponse createByDocTemplate = EsignHttpHelper . doCommHttp ( serverUrl , apiAddr , requestType , jsonParams , header , debug ) ;
if ( createByDocTemplate . getStatus ( ) ! = 200 | | createByDocTemplate . getBody ( ) = = null ) {
throw new EsignDemoException ( " 请求失败,返回状态码: " + createByDocTemplate . getStatus ( ) ) ;
}
JSONObject jsonObject = JSONUtil . parseObj ( createByDocTemplate . getBody ( ) ) ;
Integer code = jsonObject . getInt ( " code " ) ;
String signFlowId = ( String ) jsonObject . getByPath ( " data.signFlowId " ) ;
if ( code = = null | | code ! = 0 | | StrUtil . isBlank ( signFlowId ) ) {
throw new RuntimeException ( " 请求失败,返回状态码: " + createByDocTemplate . getStatus ( ) ) ;
}
/ / 合作方签署状态 : - 1 : 预备数据阶段 ; 1 - 等待签署 ; 2 - 已完成 ( 所有签署方完成签署 ) 3 - 已撤销 ( 发起方撤销签署任务 ) 5 - 已过期 ( 签署截止日到期后触发 ) 7 - 已拒签 ( 签署方拒绝签署 )
Boolean success = updateContractFlowIdAndFileUrl ( esignContract . getId ( ) , signFlowId , CommonConstant . CONTRACT_SIGN_STA_ING , null ) ;
if ( ! success ) {
throw new RuntimeException ( " 更新合同流程状态失败 " ) ;
}
return CommonResult . success ( " 合同流程创建成功, 合同流程ID: " + signFlowId ) ;
} catch ( EsignDemoException e ) {
throw new RuntimeException ( e ) ;
}
}
/ * *
* 签署流程结束通知
*
* @return
* /
@Override
public ResponseEntity < String > signAsyncNotify ( HttpServletRequest request , ServerHttpResponse response , String requestBody ) {
log . debug ( " 签署流程结束通知:body >>> {} " , requestBody ) ;
log . debug ( " 签署流程结束通知:header >>> {} " , request . getParameterMap ( ) ) ;
/ / 异步通知获取到的header头中的签名值 : X - Tsign - Open - App - Id
String reqAppId = request . getHeader ( " X-Tsign-Open-App-Id " ) ;
/ / 异步通知获取到的header头中的签名值 : X - Tsign - Open - SIGNATURE
String signture = request . getHeader ( " X-Tsign-Open-SIGNATURE " ) ;
/ / 异步通知获取到的header头中的时间戳 : X - Tsign - Open - TIMESTAMP
String timestamp = request . getHeader ( " X-Tsign-Open-TIMESTAMP " ) ;
if ( StrUtil . isBlank ( reqAppId ) | | StrUtil . isBlank ( signture ) | | StrUtil . isBlank ( timestamp ) ) {
return new ResponseEntity < > ( new JSONObject ( ) . put ( " code " , 400 ) . put ( " msg " , " 缺少必要参数 " ) . toString ( ) , HttpStatus . INTERNAL_SERVER_ERROR ) ;
}
if ( ! reqAppId . equals ( appId ) ) {
return new ResponseEntity < > ( new JSONObject ( ) . put ( " code " , 400 ) . put ( " msg " , " appId 校验失败 " ) . toString ( ) , HttpStatus . INTERNAL_SERVER_ERROR ) ;
}
/ / 按照规则进行加密
String signData = timestamp + requestBody ;
String mySignature = getSignature ( signData , appSecret , " HmacSHA256 " , " UTF-8 " ) ;
log . debug ( " 加密出来的签名值:----------->>>>>> " + mySignature ) ;
log . debug ( " header里面的签名值: ---------->>>>>> " + signture ) ;
if ( ! mySignature . equals ( signture ) ) {
return new ResponseEntity < > ( new JSONObject ( ) . put ( " code " , 400 ) . put ( " msg " , " 签名校验不匹配 " ) . toString ( ) , HttpStatus . INTERNAL_SERVER_ERROR ) ;
}
/ / 处理业务逻辑
JSONObject reqBodyJSON = JSONUtil . parseObj ( requestBody ) ;
String action = reqBodyJSON . getStr ( " action " ) ;
String signFlowId = reqBodyJSON . getStr ( " signFlowId " ) ;
String signFlowStatus = reqBodyJSON . getStr ( " signFlowStatus " ) ;
if ( StrUtil . isBlank ( action ) | | StrUtil . isBlank ( signFlowId ) | | StrUtil . isBlank ( signFlowStatus ) ) {
return new ResponseEntity < > ( new JSONObject ( ) . put ( " code " , 400 ) . put ( " msg " , " 返回数据不全 " ) . toString ( ) , HttpStatus . INTERNAL_SERVER_ERROR ) ;
}
/ / 获取正式盖章合同文件 , 上传到 oss 服务器 , 更状态 , 保存数据
if ( action . equals ( " SIGN_FLOW_COMPLETE " ) ) { / / 签署流程完毕
/ / 获取正式盖章合同文件地址
String downloadUrl = getSignedContractFileUrl ( signFlowId ) ;
/ / 更新合同流程状态和文件地址
boolean success = updateContractFlowStatusAndFileUrlBySignFlowId ( signFlowId , CommonConstant . CONTRACT_SIGN_STA_FINISH , downloadUrl ) ;
if ( success & & StrUtil . isNotBlank ( downloadUrl ) ) {
return new ResponseEntity < > ( new JSONObject ( ) . put ( " code " , 200 ) . put ( " msg " , " success " ) . toString ( ) , HttpStatus . OK ) ;
}
}
return new ResponseEntity < > ( new JSONObject ( ) . put ( " code " , 400 ) . put ( " msg " , " 更新数据失败 " ) . toString ( ) , HttpStatus . INTERNAL_SERVER_ERROR ) ;
}
/ * *
* 更新合同流程ID和正式盖章合同文件地址 , 并上传到 oss 服务器
* < p >
@ -97,33 +262,125 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
*
* @param mchMobile 商家注册手机号
* @param contractFileId 未签署合同文件Id
* @param signFlowId 合同签署流程ID ( signFlowId和fileUrl 起码一个是必填的 )
* @param fileUrl E签宝的正式签署合同文件地址 ( 可空 )
* @param signFlowId 合同签署流程ID ( signFlowId和fileUrl 、 signFlowStatus 起码一个是必填的 )
* @param signFlowStatus 签署流程状态 ( signFlowId和fileUrl 、 signFlowStatus 起码一个是必填的 )
* @param fileUrl E签宝的正式签署合同文件地址 ( 可空 ) ( signFlowId和fileUrl 、 signFlowStatus 起码一个是必填的 )
* @return
* /
@Override
public Boolean updateContractFlowIdAndFileUrl ( String mchMobile , String contractFileId , String signFlowId , String fileUrl ) {
public Boolean updateContractFlowIdAndFileUrl ( String mchMobile , String contractFileId , String signFlowId , Integer signFlowStatus , String fileUrl ) {
if ( StrUtil . isBlank ( mchMobile ) | | StrUtil . isBlank ( contractFileId ) | | ( StrUtil . isBlank ( signFlowId ) & & StrUtil . isBlank ( fileUrl ) ) ) {
return false ;
}
EsignContract esignContract = getEsignContractByMchMobile ( mchMobile ) ;
if ( esignContract = = null ) {
return false ;
}
UpdateWrapper < EsignContract > queryWrapper = new UpdateWrapper < > ( ) ;
queryWrapper . eq ( " mch_mobile " , mchMobile ) ;
queryWrapper . eq ( " contract_file_id " , contractFileId ) ;
queryWrapper . eq ( " status " , CommonConstant . Enable ) ;
queryWrapper . eq ( " id " , esignContract . getId ( ) ) ;
if ( StrUtil . isNotBlank ( signFlowId ) ) {
queryWrapper . set ( " sign_flow_id " , signFlowId ) ;
}
if ( signFlowStatus ! = null ) {
queryWrapper . set ( " sign_flow_status " , signFlowStatus ) ;
}
if ( StrUtil . isNotBlank ( fileUrl ) ) {
queryWrapper . set ( " signed_contract_url " , fileUrl ) ;
/ / REMARK 把合同文件 url 上传到cos服务器
String cosFileName = TENGXUN_DEFAULT_DIR . concat ( " / " ) . concat ( " contract " )
. concat ( " / " )
. concat ( esignContract . getMch_biz_license ( ) ) . concat ( " / " )
. concat ( " signed " ) . concat ( " / " )
. concat ( contractFileId ) . concat ( " .pdf " ) ;
. concat ( esignContract . getContract_file_id ( ) ) . concat ( " .pdf " ) ;
/ / 上传到cos服务器
String localFileUrl = ossService . uploadObject4OSS ( fileUrl , cosFileName ) ;
queryWrapper . set ( " local_contract_url " , localFileUrl ) ;
}
return this . update ( queryWrapper ) ;
}
/ * *
* 更新合同流程ID和文件地址和状态
*
* @param id 自增Id
* @param signFlowId 签署流程Id
* @param signFlowStatus 签署流程状态
* @param fileUrl 盖章合同文件地址
* @return
* /
@Override
public Boolean updateContractFlowIdAndFileUrl ( Long id , String signFlowId , Integer signFlowStatus , String fileUrl ) {
if ( ObjectUtil . isEmpty ( id ) | | ( StrUtil . isBlank ( signFlowId ) & & ObjectUtil . isEmpty ( signFlowStatus ) & & StrUtil . isBlank ( fileUrl ) ) ) {
return false ;
}
EsignContract esignContract = get ( id ) ;
if ( esignContract = = null ) {
return false ;
}
UpdateWrapper < EsignContract > queryWrapper = new UpdateWrapper < > ( ) ;
queryWrapper . eq ( " id " , id ) ;
if ( StrUtil . isNotBlank ( signFlowId ) ) {
queryWrapper . set ( " sign_flow_id " , signFlowId ) ;
}
if ( signFlowStatus ! = null ) {
queryWrapper . set ( " sign_flow_status " , signFlowStatus ) ;
}
if ( StrUtil . isNotBlank ( fileUrl ) ) {
queryWrapper . set ( " signed_contract_url " , fileUrl ) ;
/ / REMARK 把合同文件 url 上传到cos服务器
String cosFileName = TENGXUN_DEFAULT_DIR . concat ( " / " ) . concat ( " contract " )
. concat ( " / " )
. concat ( esignContract . getMch_biz_license ( ) ) . concat ( " / " )
. concat ( " signed " ) . concat ( " / " )
. concat ( esignContract . getContract_file_id ( ) ) . concat ( " .pdf " ) ;
/ / 上传到cos服务器
String localFileUrl = ossService . uploadObject4OSS ( fileUrl , cosFileName ) ;
queryWrapper . set ( " local_contract_url " , localFileUrl ) ;
}
return this . update ( queryWrapper ) ;
}
@Override
public Boolean updateContractFlowStatusAndFileUrlBySignFlowId ( String signFlowId , Integer signFlowStatus , String fileUrl ) {
if ( StrUtil . isBlank ( signFlowId ) | | ( ObjectUtil . isEmpty ( signFlowStatus ) & & StrUtil . isBlank ( fileUrl ) ) ) {
return false ;
}
EsignContract esignContract = getEsignContractBySignFlowId ( signFlowId ) ;
if ( esignContract = = null ) {
return false ;
}
UpdateWrapper < EsignContract > queryWrapper = new UpdateWrapper < > ( ) ;
queryWrapper . eq ( " id " , esignContract . getId ( ) ) ;
if ( signFlowStatus ! = null ) {
queryWrapper . set ( " sign_flow_status " , signFlowStatus ) ;
}
if ( StrUtil . isNotBlank ( fileUrl ) ) {
queryWrapper . set ( " signed_contract_url " , fileUrl ) ;
/ / REMARK 把合同文件 url 上传到cos服务器
String cosFileName = TENGXUN_DEFAULT_DIR . concat ( " / " ) . concat ( " contract " )
. concat ( " / " )
. concat ( esignContract . getMch_biz_license ( ) ) . concat ( " / " )
. concat ( " signed " ) . concat ( " / " )
. concat ( esignContract . getContract_file_id ( ) ) . concat ( " .pdf " ) ;
/ / 上传到cos服务器
String localFileUrl = ossService . uploadObject4OSS ( fileUrl , cosFileName ) ;
queryWrapper . set ( " local_contract_url " , localFileUrl ) ;
@ -185,6 +442,85 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
return saveOrUpdateByMchMobile ( esignContract ) ;
}
/ * *
* 根据商家注册手机号 , 获取一条合同信息
*
* @param mchMobile
* @return
* /
@Override
public EsignContract getEsignContractByMchMobile ( String mchMobile ) {
QueryWrapper < EsignContract > queryWrapper = new QueryWrapper < > ( ) ;
queryWrapper . eq ( " mch_mobile " , mchMobile ) ;
queryWrapper . eq ( " status " , CommonConstant . Enable ) ;
List < EsignContract > esignContractList = this . list ( queryWrapper ) ;
if ( CollectionUtil . isEmpty ( esignContractList ) ) {
return null ;
}
return esignContractList . get ( 0 ) ;
}
@Override
public EsignContract getEsignContractBySignFlowId ( String signFlowId ) {
QueryWrapper < EsignContract > queryWrapper = new QueryWrapper < > ( ) ;
queryWrapper . eq ( " sign_flow_id " , signFlowId ) ;
queryWrapper . eq ( " status " , CommonConstant . Enable ) ;
List < EsignContract > esignContractList = this . list ( queryWrapper ) ;
if ( CollectionUtil . isEmpty ( esignContractList ) ) {
return null ;
}
return esignContractList . get ( 0 ) ;
}
/ * *
* 根据合同流程ID , 获取完成签署生效的合同文件地址
* < p >
* 收到异步通知 , 签署完成之后 , 获取合同文件地址 , 保存并上传到 oss
*
* @param signFlowId
* @return
* /
@Override
public String getSignedContractFileUrl ( String signFlowId ) {
String apiAddr = " /v3/sign-flow/ " + signFlowId + " /file-download-url " ;
try {
/ / 请求方法
EsignRequestType requestType = EsignRequestType . GET ;
/ / 生成签名鉴权方式的的header
Map < String , String > header = EsignHttpHelper . signAndBuildSignAndJsonHeader ( appId , appSecret , null , requestType . name ( ) , apiAddr , true ) ;
/ / 发起接口请求
EsignHttpResponse esignHttpResponse = EsignHttpHelper . doCommHttp ( serverUrl , apiAddr , requestType , null , header , debug ) ;
if ( esignHttpResponse . getStatus ( ) ! = 200 | | StrUtil . isEmpty ( esignHttpResponse . getBody ( ) ) ) {
return null ;
}
JSONObject jsonObject = JSONUtil . parseObj ( esignHttpResponse . getBody ( ) ) ;
if ( jsonObject = = null | | ! jsonObject . getInt ( " code " ) . equals ( 0 )
| | ObjectUtil . isEmpty ( jsonObject . get ( " data " ) )
| | ObjectUtil . isEmpty ( jsonObject . getByPath ( " data.files " ) ) ) {
return null ;
}
JSONArray files = jsonObject . getJSONArray ( " data.files " ) ;
if ( CollectionUtil . isEmpty ( files ) ) {
return null ;
}
return files . getJSONObject ( 0 ) . getStr ( " downloadUrl " ) ;
} catch ( EsignDemoException e ) {
/ / throw new RuntimeException ( e ) ;
log . error ( e . getMessage ( ) , e ) ;
return null ;
}
}
/ / e签宝签名相关方法
/ * *
* 根据商家的注册手机号 , 新增或更新签署合同记录 。
*
@ -203,7 +539,7 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
}
/ * *
* 组织生成签署合同的请求参数 。
* ( 重要 ) 组织生成签署合同的请求参数 。
*
* @param shopMerchEntry
* @param esignPlatformInfo
@ -229,7 +565,7 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
signFlowConfig . put ( " signFlowTitle " , contractName ) ;
signFlowConfig . put ( " signFlowExpireTime " , System . currentTimeMillis ( ) + 90L * 24 * 60 * 60 * 1000 ) ; / / 90天
signFlowConfig . put ( " autoFinish " , true ) ;
signFlowConfig . put ( " notifyUrl " , main_domain + " /admin/shop/esign/asyn /notify" ) ;
signFlowConfig . put ( " notifyUrl " , main_domain + " /admin/shop/esign/asyn c /notify" ) ;
signFlowConfig . putByPath ( " signFlowConfig.redirectUrl " , " wechat://back " ) ;
reqParams . put ( " signFlowConfig " , signFlowConfig ) ;
@ -275,7 +611,7 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
/ / 个人
platSigner . put ( " signerType " , 0 ) ;
platSigner . putByPath ( " psnSignerInfo.psnAccount " , esignPlatformInfo . getLegal_person_mobile ( ) ) ;
platSigner . putByPath ( " psnSignerInfo.psnInfo.psnName " , shopMerchEntry . getLegal_person_name ( ) ) ;
platSigner . putByPath ( " psnSignerInfo.psnInfo.psnName " , esignPlatformInfo . getLegal_person_name ( ) ) ;
}
/ / 加入乙方平台方信息
signers . add ( platSigner ) ;