PHP项目如何对接人脸核验接口?

wen PHP项目 34

PHP项目对接人脸核验接口完整指南

准备工作

  1. 选择服务商:常见的人脸核验服务商

    PHP项目如何对接人脸核验接口?

    • 阿里云人脸核身
    • 腾讯云人脸核身
    • 百度云人脸识别
    • 商汤科技
    • 旷视科技(Face++)
  2. 获取必要信息

    • API密钥(API Key/Secret Key)
    • 接口地址(Endpoint)
    • SDK或API文档

基础对接流程

<?php
/**
 * 人脸核验接口对接示例
 * 以腾讯云人脸核身为例
 */
class FaceVerification {
    private $secretId;
    private $secretKey;
    private $endpoint = "https://faceid.tencentcloudapi.com";
    public function __construct($secretId, $secretKey) {
        $this->secretId = $secretId;
        $this->secretKey = $secretKey;
    }
    /**
     * 获取人脸核验结果
     * @param string $imageBase64 人脸图片base64
     * @param string $idCardNumber 身份证号
     * @param string $name 姓名
     * @return array
     */
    public function verifyFace($imageBase64, $idCardNumber, $name) {
        $action = "IdCardVerification";
        $version = "2018-03-01";
        $region = "ap-guangzhou";
        $params = [
            "ImageBase64" => $imageBase64,
            "IdCardNumber" => $idCardNumber,
            "Name" => $name
        ];
        // 调用API
        $result = $this->makeRequest($action, $version, $region, $params);
        return json_decode($result, true);
    }
    /**
     * 发送请求(简化版签名)
     */
    private function makeRequest($action, $version, $region, $params) {
        // 1. 准备请求参数
        $payload = json_encode($params);
        // 2. 生成签名(实际项目中需要使用完整的TC3-HMAC-SHA256签名算法)
        $timestamp = time();
        $signature = $this->generateSignature($payload, $timestamp);
        // 3. 发送HTTP请求
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->endpoint);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'X-TC-Action: ' . $action,
            'X-TC-Version: ' . $version,
            'X-TC-Region: ' . $region,
            'X-TC-Timestamp: ' . $timestamp,
            'Authorization: ' . $signature
        ]);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        if ($httpCode != 200) {
            throw new Exception("API请求失败: " . $response);
        }
        return $response;
    }
    /**
     * 生成签名(简化版,实际需使用完整算法)
     */
    private function generateSignature($payload, $timestamp) {
        // 实际项目中需要实现完整的TC3-HMAC-SHA256签名
        // 这里仅作为示例,实际应参考官方SDK
        return base64_encode(hash_hmac('sha256', $payload, $this->secretKey, true));
    }
}
// 使用示例
try {
    $faceVerification = new FaceVerification('你的SecretId', '你的SecretKey');
    // 读取图片并转为base64
    $imagePath = '/path/to/face_image.jpg';
    $imageBase64 = base64_encode(file_get_contents($imagePath));
    // 执行核验
    $result = $faceVerification->verifyFace(
        $imageBase64,
        '110101199001011234',
        '张三'
    );
    if ($result['Result'] == 'Success') {
        echo "核验成功!";
        print_r($result['Description']);
    } else {
        echo "核验失败:" . $result['Description'];
    }
} catch (Exception $e) {
    echo "错误:" . $e->getMessage();
}

使用官方SDK(推荐方式)

腾讯云示例:

// 使用Composer安装
// composer require tencentcloud/tencentcloud-sdk-php
require_once 'vendor/autoload.php';
use TencentCloud\Common\Credential;
use TencentCloud\Common\Profile\ClientProfile;
use TencentCloud\Common\Profile\HttpProfile;
use TencentCloud\Faceid\V20180301\FaceidClient;
use TencentCloud\Faceid\V20180301\Models\IdCardVerificationRequest;
// 实例化认证对象
$cred = new Credential("你的SecretId", "你的SecretKey");
$httpProfile = new HttpProfile();
$httpProfile->setEndpoint("faceid.tencentcloudapi.com");
$clientProfile = new ClientProfile();
$clientProfile->setHttpProfile($httpProfile);
$client = new FaceidClient($cred, "ap-guangzhou", $clientProfile);
// 创建请求对象
$req = new IdCardVerificationRequest();
$req->ImageBase64 = base64_encode(file_get_contents('face.jpg'));
$req->IdCardNumber = '110101199001011234';
$req->Name = '张三';
// 执行请求
$resp = $client->IdCardVerification($req);
print_r($resp);

阿里云示例:

// composer require alibabacloud/facebody-20191230
use AlibabaCloud\Facebody\FacebodyClient;
use AlibabaCloud\Facebody\Models\RecognizeFaceRequest;
$client = new FacebodyClient([
    'regionId' => 'cn-shanghai',
    'accessKeyId' => '你的AccessKey',
    'accessSecret' => '你的AccessSecret',
]);
$request = new RecognizeFaceRequest();
$request->imageURL = 'https://example.com/face.jpg';
// 或者使用本地图片
// $request->imageContent = file_get_contents('face.jpg');
try {
    $response = $client->recognizeFace($request);
    print_r($response->toArray());
} catch (Exception $e) {
    echo $e->getMessage();
}

完整功能实现示例

<?php
/**
 * 完整的人脸核验系统
 */
class FaceAuthSystem {
    private $config;
    private $db;
    public function __construct($config) {
        $this->config = $config;
        $this->db = new PDO($config['db_dsn'], $config['db_user'], $config['db_pass']);
    }
    /**
     * 用户注册时进行人脸核验
     */
    public function registerWithFace($userId, $faceImage, $idCard, $name) {
        try {
            // 1. 身份证实名认证 + 人脸比对
            $verifyResult = $this->callFaceApi($faceImage, $idCard, $name);
            if ($verifyResult['code'] !== 0) {
                return ['success' => false, 'error' => '人脸核验失败'];
            }
            // 2. 保存核验记录
            $this->saveVerificationLog($userId, $verifyResult);
            // 3. 可选:保存人脸特征
            $faceFeature = $this->extractFaceFeature($faceImage);
            $this->saveFaceFeature($userId, $faceFeature);
            return ['success' => true, 'data' => $verifyResult];
        } catch (Exception $e) {
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    /**
     * 登录时进行人脸验证
     */
    public function loginWithFace($userId, $faceImage) {
        try {
            // 1. 获取已保存的人脸特征
            $savedFeature = $this->getFaceFeature($userId);
            // 2. 提取当前人脸特征
            $currentFeature = $this->extractFaceFeature($faceImage);
            // 3. 特征比对
            $similarity = $this->compareFeatures($savedFeature, $currentFeature);
            if ($similarity < 0.8) { // 相似度阈值
                return ['success' => false, 'error' => '人脸验证失败'];
            }
            // 4. 生成登录令牌
            $token = $this->generateToken($userId);
            return ['success' => true, 'token' => $token];
        } catch (Exception $e) {
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    /**
     * 调用人脸核验API
     */
    private function callFaceApi($faceImage, $idCard, $name) {
        // 根据使用的服务商调用对应API
        switch ($this->config['provider']) {
            case 'tencent':
                return $this->tencentFaceVerify($faceImage, $idCard, $name);
            case 'aliyun':
                return $this->aliyunFaceVerify($faceImage, $idCard, $name);
            default:
                throw new Exception("不支持的人脸核验服务商");
        }
    }
    /**
     * 腾讯云人脸核验
     */
    private function tencentFaceVerify($faceImage, $idCard, $name) {
        require_once 'vendor/autoload.php';
        $cred = new Credential($this->config['secret_id'], $this->config['secret_key']);
        $httpProfile = new HttpProfile();
        $httpProfile->setEndpoint("faceid.tencentcloudapi.com");
        $clientProfile = new ClientProfile();
        $clientProfile->setHttpProfile($httpProfile);
        $client = new FaceidClient($cred, "ap-guangzhou", $clientProfile);
        $req = new IdCardVerificationRequest();
        $req->ImageBase64 = base64_encode($faceImage);
        $req->IdCardNumber = $idCard;
        $req->Name = $name;
        try {
            $resp = $client->IdCardVerification($req);
            return json_decode($resp->toJsonString(), true);
        } catch (Exception $e) {
            return ['code' => -1, 'message' => $e->getMessage()];
        }
    }
    // 其他辅助方法...
}

安全最佳实践

<?php
/**
 * 安全配置示例
 */
class SecurityConfig {
    // 1. API密钥管理
    private static function getApiKeys() {
        // 从环境变量或配置文件读取,不要硬编码
        return [
            'secret_id' => getenv('FACE_API_SECRET_ID'),
            'secret_key' => getenv('FACE_API_SECRET_KEY')
        ];
    }
    // 2. 请求频率限制
    public static function checkRateLimit($userId) {
        $redis = new Redis();
        $key = "face_verify:{$userId}:" . date('Y-m-d-H');
        $count = $redis->incr($key);
        if ($count === 1) {
            $redis->expire($key, 3600); // 1小时过期
        }
        if ($count > 10) { // 每小时最多10次
            throw new Exception("请求过于频繁,请稍后再试");
        }
    }
    // 3. 图片安全验证
    public static function validateImage($imageData) {
        // 检查文件大小
        if (strlen($imageData) > 5 * 1024 * 1024) { // 5MB
            throw new Exception("图片过大");
        }
        // 检查图片格式
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mimeType = finfo_buffer($finfo, $imageData);
        finfo_close($finfo);
        $allowedTypes = ['image/jpeg', 'image/png', 'image/webp'];
        if (!in_array($mimeType, $allowedTypes)) {
            throw new Exception("不支持的图片格式");
        }
        return true;
    }
}

错误处理与日志

<?php
/**
 * 错误处理及日志记录
 */
class FaceLogHandler {
    private $logFile;
    public function __construct($logFile) {
        $this->logFile = $logFile;
    }
    public function logError($message, $context = []) {
        $log = [
            'timestamp' => date('Y-m-d H:i:s'),
            'message' => $message,
            'context' => $context,
            'ip' => $_SERVER['REMOTE_ADDR'] ?? 'unknown'
        ];
        file_put_contents(
            $this->logFile,
            json_encode($log) . PHP_EOL,
            FILE_APPEND
        );
    }
    public function handleApiError($response, $requestData) {
        $errorCode = $response['code'] ?? 'unknown';
        $errorMsg = $response['message'] ?? '未知错误';
        $this->logError("人脸核验API错误", [
            'error_code' => $errorCode,
            'error_message' => $errorMsg,
            'request_data' => $this->maskSensitiveData($requestData)
        ]);
        return [
            'success' => false,
            'error' => "核验失败,请稍后重试"
        ];
    }
    private function maskSensitiveData($data) {
        // 脱敏处理
        if (isset($data['idCard'])) {
            $data['idCard'] = substr($data['idCard'], 0, 4) . '********' . 
                              substr($data['idCard'], -4);
        }
        return $data;
    }
}

前端对接建议

<!-- 前端调用示例 -->
<!DOCTYPE html>
<html>
<head>人脸核验</title>
</head>
<body>
    <div id="face-container">
        <video id="video" width="400" height="300" autoplay></video>
        <canvas id="canvas" style="display:none;"></canvas>
        <button onclick="startVerification()">开始核验</button>
    </div>
    <script>
    async function startVerification() {
        try {
            // 1. 获取摄像头权限
            const stream = await navigator.mediaDevices.getUserMedia({ 
                video: { width: 400, height: 300 } 
            });
            const video = document.getElementById('video');
            video.srcObject = stream;
            // 2. 拍照
            setTimeout(() => {
                const canvas = document.getElementById('canvas');
                canvas.width = video.videoWidth;
                canvas.height = video.videoHeight;
                canvas.getContext('2d').drawImage(video, 0, 0);
                // 3. 转换为base64
                const imageData = canvas.toDataURL('image/jpeg', 0.8);
                // 4. 发送到后端
                fetch('/api/face-verify', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        image: imageData.split(',')[1], // 移除data:image/jpeg;base64,
                        idCard: document.getElementById('idCard').value,
                        name: document.getElementById('name').value
                    })
                })
                .then(response => response.json())
                .then(data => {
                    if (data.success) {
                        alert('核验成功!');
                    } else {
                        alert('核验失败:' + data.error);
                    }
                })
                .catch(error => console.error('Error:', error));
                // 5. 停止摄像头
                stream.getTracks().forEach(track => track.stop());
            }, 1000);
        } catch (error) {
            console.error('摄像头错误:', error);
            alert('无法访问摄像头,请检查权限设置');
        }
    }
    </script>
</body>
</html>

注意事项

  1. 成本控制:人脸核验API通常按次收费,注意控制调用频率和优化业务逻辑

  2. 合规要求

    • 遵守《个人信息保护法》
    • 获得用户明确授权
    • 提供数据删除机制
  3. 性能优化

    • 使用队列处理高并发请求
    • 图片大小控制在500KB以内
    • 添加缓存机制
  4. 测试环境

    • 使用沙箱环境测试
    • 准备测试用的人脸图片和身份证信息
    • 注意测试数据的合规性

这是一个完整的PHP人脸核验接口对接指南,你可以根据实际需求选择合适的方式实现,建议优先使用官方SDK,更加稳定和安全。

抱歉,评论功能暂时关闭!