腾讯云人脸核身增强版PHP端对接

最近项目上要使用腾讯云的人脸核身进行实名论证,使用的是增强版的,并开通了SDK对接和H5(非微信浏览器)对接两种方式。

H5(非微信浏览器)方式需要服务端先对接,传入姓名和身份证号后发起认证,返回一个认证链接给前端,前端打开WebView,认证完成后会自动跳转到回调页面更新认证结果。

服务端我使用的是PHP,贴下核心认证类的代码。

<?php
namespace third;
use GuzzleHttp\Client;

/**
 * 腾讯云 人脸核身(增强版)
 */

class FaceVerify{
    // 业务流程唯一标识,即 WBappid,可参考 获取 WBappid 指引在人脸核身控制台内申请
    protected $app_id;
    // WBappid 对应的密钥,申请 WBappid 时得到,可参考 获取 WBappid 指引在人脸核身控制台内申请
    protected $secret;
    // 授权类型,默认值为:client_credential(必须小写
    private $grant_type = 'client_credential';
    // 版本号,默认值为:1.0.0
    private $version = '1.0.0';
    // 获取AccessToken 接口链接
    private $getAccessTokenUrl = 'https://kyc1.qcloud.com/api/oauth2/access_token';
    // 获取SignTicket 接口链接
    private $getSignTicketUrl = 'https://kyc1.qcloud.com/api/oauth2/api_ticket';
    // 合作方后台上传身份信息
    private $getH5FaceidUrl = 'https://kyc1.qcloud.com/api/server/getAdvFaceId';
    // 认证完成回调跳转地址
    protected $callbackUrl='';

    /**
     * 构造函数
     * @param $appid  合作方appid
     * @param $secret  合作方secret
     * @param $callback_url  合作方回调地址
     */
    function __construct($appid, $secret, $callback_url){
        $this->app_id = $appid;
        $this->secret = $secret;
        $this->callbackUrl = $callback_url;
    }

    /**
     * 合作方后台上传身份信息
     * 并返回h5人脸核身链接
     * https://cloud.tencent.com/document/product/1007/61073
     * $orderNo  订单编码
     * $name  姓名
     * $idNo  身份证号
     * $userId  用户ID
     */
    public function getH5Faceverify($userId, $name, $idNo, $orderNo){
        //$userId必须是字符串
        $userId = $userId . "";
        $post_url = $this->getH5FaceidUrl.'?orderNo='.$orderNo;
        $sign_ticket = $this->getSignTicket();
        $nonce = $this->getNonce(32);
        //5个参数参与签名
        $arr = [
            $this->app_id,
            $userId,
            $nonce,
            $this->version,
            $sign_ticket
        ];
        asort($arr, SORT_STRING);
        $str = implode('', $arr);
        $sign = sha1($str);
        $post = [
            'appId' => $this->app_id,
            'orderNo' => $orderNo,
            'name' => $name,
            'idNo' => $idNo,
            'userId' => $userId,
            'version' => $this->version,
            'sign' => $sign,
            'nonce' => $nonce
        ];
        $client = new Client();
        $response = $client->request('POST', $post_url, [
            'json'  => $post,
        ])->getBody()->getContents();
        $result = json_decode($response, true);
        if ($result['code'] != 0){
            return ['code' => 0, 'msg' => $result['msg']];
        }

        $optimalDomain = $result['result']['optimalDomain'];
        $faceId = $result['result']['faceId'];
        $nonce = $this->getNonce(32);

        $url = $this->getH5Url($optimalDomain, $orderNo, $userId, $faceId, $sign_ticket, $nonce);

        return ['code' => 1, 'msg' => '发起成功', 'url' => $url];
    }

    /**
     * 生成签名并拼接人脸核身url
     */
    private function getH5Url($optimalDomain, $orderNo, $userId, $faceId, $ticket, $nonce){
        //7个参数参与签名
        $arr = [
            $this->app_id
            ,$orderNo
            ,$userId
            ,$this->version
            ,$faceId
            ,$ticket
            ,$nonce
        ];
        asort($arr, SORT_STRING);
        $str = implode('', $arr);
        $sign = sha1($str);
        $url = 'https://'.$optimalDomain.'/api/web/login?'
            .'appId='.$this->app_id
            .'&version='.$this->version
            .'&nonce='.$nonce
            .'&orderNo='.$orderNo
            .'&faceId='.$faceId
            .'&url='. urlencode($this->callbackUrl)
            .'&userId='.$userId
            .'&from=browser'
            .'&sign='.$sign;
        return $url;
    }

    /**
     * 获取随机数
     */
    private function getNonce($num){
        $str="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        $key = "";
        for($i=0;$i<$num;$i++) {
            $key .= $str[mt_rand(0,32)];    //生成php随机数
        }
        return $key;
    }

    /**
     * 获取 SIGN ticket
     * 文档: https://cloud.tencent.com/document/product/1007/57613
     */
    private function getSignTicket(){
        @mkdir(ROOT_PATH . "/runtime/faceverify/", 0777, true);
        $file_path = RUNTIME_PATH. '/faceverify/sign_ticket.txt';
        if(file_exists($file_path)){
            $data = file_get_contents($file_path);
            $data_arr = json_decode($data, true);
        }
        if (!isset($data_arr['expire_time']) || $data_arr['expire_time']<time()){

            $url = $this->getSignTicketUrl
                .'?app_id='.$this->app_id
                .'&access_token='.$this->getAccessToken()
                .'&type=SIGN&version='.$this->version;
            $data = file_get_contents($url);
            $data_arr = json_decode($data, true);
            $data_arr = [
                'expire_time' => time()+3600,
                'sign_ticket' => $data_arr['tickets'][0]['value'],
            ];
            file_put_contents($file_path, json_encode($data_arr, JSON_UNESCAPED_UNICODE));
        }
        return $data_arr['sign_ticket'];
    }

    /**
     * 获取 access_token
     * 文档: https://cloud.tencent.com/document/product/1007/57603
     */
    private function getAccessToken(){
        @mkdir(ROOT_PATH . "/runtime/faceverify/", 0777, true);
        $file_path = RUNTIME_PATH. '/faceverify/access_token.txt';
        if(file_exists($file_path)){
            $data = file_get_contents($file_path);
            $data_arr = json_decode($data, true);
        }
        if (!isset($data_arr['expire_time']) || $data_arr['expire_time']<time()){

            $url = $this->getAccessTokenUrl
                .'?app_id='.$this->app_id
                .'&secret='.$this->secret
                .'&grant_type='.$this->grant_type
                .'&version='.$this->version;
            $data = file_get_contents($url);
            $data_arr = json_decode($data, true);
            file_put_contents($file_path, json_encode([
                'expire_time' => time()+7200,
                'access_token' => $data_arr['access_token'],
            ], JSON_UNESCAPED_UNICODE));
        }
        return $data_arr['access_token'];
    }
}

使用方法:

use \third\FaceVerify;

$app_id = ""; //开通服务的APPID
$secert = ""; //开通服务的APPID
$callback_url = "http://xxx.com/xxx/xx";  //回调地址

$verify = new FaceVerify($app_id, $secert, $callback_url);

$user_id = "1";
$name = "";  //姓名,要用真的
$idcard = ""; //身份证号,也要用真的,不然会发起失败
$order_no = date('YmdHis') . rand(1000, 9999);

$result = $verify->getH5Faceverify($user_id, $name, $idcard, $order_no);

发起成功的话会返回如下格式的数据

['code' => 1, 'msg' => '发起成功', 'url' = > 'https://....']

以上代码也大致适用于Plus版的人脸核身,参照官方文档改下接口链接和少部分参数即可。

Leave a Comment

豫ICP备19001387号-1