PHP项目对接人脸核验接口完整指南
准备工作
-
选择服务商:常见的人脸核验服务商

- 阿里云人脸核身
- 腾讯云人脸核身
- 百度云人脸识别
- 商汤科技
- 旷视科技(Face++)
-
获取必要信息
- 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>
注意事项
-
成本控制:人脸核验API通常按次收费,注意控制调用频率和优化业务逻辑
-
合规要求:
- 遵守《个人信息保护法》
- 获得用户明确授权
- 提供数据删除机制
-
性能优化:
- 使用队列处理高并发请求
- 图片大小控制在500KB以内
- 添加缓存机制
-
测试环境:
- 使用沙箱环境测试
- 准备测试用的人脸图片和身份证信息
- 注意测试数据的合规性
这是一个完整的PHP人脸核验接口对接指南,你可以根据实际需求选择合适的方式实现,建议优先使用官方SDK,更加稳定和安全。