测试环境域名:
https://identitytest.fangxinq...
key:GoexwR3Toe
secret:72e9ff5d6a49491690a4cd22eb9402b1
config配置
// 放心签配置
'FXQ_APPID' => 'GoexwR3Toe',
'FXQ_SECRET' => '72e9ff5d6a49491690a4cd22eb9402b1',
'FXQ_IDENTITYURL' => 'https://identitytest.fangxinqian.cn',
'FXQ_RESTAPI' => 'https://restapitest.fangxinqian.cn',
'FXQ_CONTRACT' => 'https://*****.pdf',
Fangxinqian.php
<?php
namespace app\common\service;
use think\Db;
use think\Config;
use think\Cache;
class Fangxinqian
{
private static $instance = null ;
public static function ins()
{
if( self::$instance == null ){
self::$instance = new self();
}
return self::$instance;
}
//签章生成
public function seal_personal($realname)
{
$token = $this->getToken();
$data = [
"name" => $realname, //真实姓名
"rtype" => 1, //返回类型(0:Base64,1:oss地址链接,默认为0)
'color' => 0, //颜色(0:红色,1:蓝色,2:黑色,默认为0)
'font' => 1, //字体(0:仿宋,1:楷体,2:黑体,默认为0)
'type' => 0, //形状(0:长方形,1:正方形,默认为0)
];
$signString = "";
$data = $this->sortParam($data);
$this->readParams($data,$signString);
$nonce = date('YmdHis').rand(111,99999);
$sign = md5(sha1(base64_encode($signString."||token=".$token."||nonce=".$nonce)));
$result = $this->serverSubmit(config('FXQ_RESTAPI').'/seal/v1/personal', $data, 'post', $token, $nonce, $sign);
// var_dump($result);
if ( !empty($result) && $result['code'] == '10000' ) {
return $result['data'];
}
return false;
}
//公安二要素
public function shiming($realname, $idcardno)
{
$token = $this->getToken();
$data = [
"realName" => $realname, //真实姓名
"idCardNo" => $idcardno, //身份证号码
];
$signString = "";
$data = $this->sortParam($data);
$this->readParams($data,$signString);
$nonce = date('YmdHis').rand(111,99999);
$sign = md5(sha1(base64_encode($signString."||token=".$token."||nonce=".$nonce)));
$result = $this->serverSubmit(config('FXQ_IDENTITYURL').'/identity/v1/2', $data, 'post', $token, $nonce, $sign);
// var_dump($result);
if ( !empty($result) && $result['code'] == '10000' ) {
return $result['data']['state'];
}
return 2;
}
//单文件签署
public function port_sign($realname, $idcardno, $seal)
{
$token = $this->getToken();
$data = [
"contract" => config('FXQ_CONTRACT'), //url地址或者base64
"type" => 1 , //合同返回类型(0:Base64,1:oss地址,默认为0)
"signDate" => [ 'enable' => 1 ], //签章日期(跟随在印章底部)
"signers"=> [
[
"name" => $realname,
"idno" => $idcardno,
"seal" => $seal,//图片
// "height" => 300, //传了此参数才会加盖骑缝章,反之则不加盖骑缝章 (建议值在100 - 600之间)
"areas" =>[
[
"x"=>114,
"y"=>66,
"page"=>1
]
]
]
],
];
$signString = "";
//排序
$data = $this->sortParam($data);
//签名加密
$this->readParams($data,$signString);
//流水号,每次请求保证唯一,五分钟之类不能重复
$nonce = date('YmdHis').rand(111,99999);
// echo "加密sign是--".$signString."||token=".$token."||nonce=".$nonce."\n";
$sign = md5(sha1(base64_encode($signString."||token=".$token."||nonce=".$nonce)));
// echo '发起签署----------------开始';
// echo "\n";
$result = $this->serverSubmit(config('FXQ_RESTAPI').'/contract/v1/port/sign', $data, 'post', $token, $nonce, $sign);
// var_dump($result);
// echo 'result:'.json_encode($result);
// echo '发起签署结果:'.$result['msg'];
// echo "\n";
// echo '发起签署----------------结束';
// echo "\n";
return $result;
}
//获取鉴权token
public function getToken()
{
$token = Cache::store('redis')->get('fangxinqian_token');
if ( empty($token) ) {
$arr = [ "key"=> config('FXQ_APPID'), "secret"=> config('FXQ_SECRET') ];
$result = $this->serverSubmit(config('FXQ_IDENTITYURL').'/auth/v1/token', $arr);
// var_dump($result);
if ( !empty($result) && $result['code'] == '10000' ) {
Cache::store('redis')->set('fangxinqian_token', $result['data'], 3600);
return $result['data'];
}
}
return $token;
}
public function serverSubmit($url, $parameter, $re = 'post', $token = "", $nonce = "", $sign = "")
{
// var_dump($url);
$parameter = json_encode($parameter,true);
if($token){
$headers[] = "Content-Type:application/json";
$headers[] = "token: ". $token;
$headers[] = "fxq-nonce: ". $nonce;
$headers[] = "fxq-sign: ". $sign;
}else{
$headers = array('Content-Type: application/json;charset=utf-8;');
}
//初始化
$curl = curl_init();
//设置抓取的url
curl_setopt($curl, CURLOPT_URL, $url);
//设置头文件的信息作为数据流输出
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
//设置请求头
curl_setopt($curl, CURLOPT_HEADER, 1);
//设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
//设置提交方式
if ($re == 'post')
{
//post提交方式
curl_setopt($curl, CURLOPT_POST, 1);
//设置post数据
curl_setopt($curl, CURLOPT_POSTFIELDS, $parameter);
}
elseif ($re == 'get')
{
}
//执行命令
$data = curl_exec($curl);
//分离头信息与数据主体
$headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
$datas['header'] = substr($data, 0, $headerSize);
$datas['body'] = substr($data, $headerSize);
//关闭URL请求
curl_close($curl);
unset($data);
//显示获得的数据
return json_decode($datas['body'], true);
}
public static function readParams($data,&$string)
{
$size = count($data);
foreach ($data as $key=>$val){
$size --;
self::readChildParams($key,json_encode($val),$string,$size);
}
return $string;
}
public static function readChildParams($key,$value,&$string,$index)
{
if(is_string($key)){
$string.= $key."=";
}
if(self::startsWith($value,"{")){
$string.="{";
self::readParams(json_decode($value,true),$string);
$string.="}";
}elseif (self::startsWith($value,"[")){
$string.="[";
$list = json_decode($value,true);
$size = count($list);
foreach ($list as $list1){
$size --;
self::readChildParams(null,json_encode($list1),$string,$size);
}
$string.="]";
}else{
//去除双引号
$string.= str_replace('"', '',json_decode($value,true));
}
if($index != 0){
$string.= "||";
}
return $string;
}
public static function startsWith($haystack, $needle, $case=true)
{
if ($case){
return strncasecmp($haystack, $needle, strlen($needle)) == 0 ;
}else{
return strncmp($haystack, $needle, strlen($needle)) == 0;
}
}
public static function sortParam(&$param)
{
if(is_array($param)){
ksort($param);
foreach ($param as &$value){
self::sortParam($value);
}
}
return $param;
}
}