You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

98 lines
3.7 KiB

package idverify
import (
"context"
"encoding/json"
"fmt"
"strings"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
tchttp "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/http"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
)
// 腾讯云 人脸核身 - 身份证二要素核验 IdCardVerification
// 文档:https://cloud.tencent.com/document/product/1007/33188
//
// Action IdCardVerification
// Version 2018-03-01
// Service faceid(域名 faceid.tencentcloudapi.com)
// 入参 Name(姓名) / IdCard(身份证号)
// 出参 Result / Description
// Result "0" = 一致
// Result "-1" = 不一致
// Result "-2".."-7" = 各类错误(格式错误、查无此人、系统升级、当日调用超限等)
//
// 走 common 包的通用调用(NewCommonClient + CommonRequest),不额外引入 faceid 子包依赖。
const (
tencentService = "faceid"
tencentAPIVersion = "2018-03-01"
tencentAction = "IdCardVerification"
tencentResultMatched = "0" // 一致
tencentResultMismatch = "-1" // 不一致
)
type tencentVerifier struct {
client *common.Client
}
// tencentResp 腾讯云响应外层统一包了一层 Response。
type tencentResp struct {
Response struct {
Result string `json:"Result"`
Description string `json:"Description"`
RequestId string `json:"RequestId"`
Error *struct {
Code string `json:"Code"`
Message string `json:"Message"`
} `json:"Error"`
} `json:"Response"`
}
func newTencent(fields map[string]string) (Verifier, error) {
if err := requireFields(fields, "secret_id", "secret_key"); err != nil {
return nil, err
}
cred := common.NewCredential(field(fields, "secret_id"), field(fields, "secret_key"))
cpf := profile.NewClientProfile()
cpf.HttpProfile.ReqMethod = "POST"
cpf.HttpProfile.ReqTimeout = 10
// 本接口不需要传 Region(文档明示),留空即可;仍允许后台配置以备将来变化。
return &tencentVerifier{client: common.NewCommonClient(cred, field(fields, "region"), cpf)}, nil
}
func (v *tencentVerifier) Provider() string { return ProviderTencent }
func (v *tencentVerifier) Verify(ctx context.Context, realname, idcardno string) (Result, error) {
req := tchttp.NewCommonRequest(tencentService, tencentAPIVersion, tencentAction)
if err := req.SetActionParameters(map[string]interface{}{
"Name": strings.TrimSpace(realname),
"IdCard": strings.TrimSpace(idcardno),
}); err != nil {
return Result{}, fmt.Errorf("idverify/tencent: 组装请求失败: %w", err)
}
resp := tchttp.NewCommonResponse()
if err := v.client.Send(req, resp); err != nil {
return Result{}, fmt.Errorf("idverify/tencent: 调用失败: %w", err)
}
var r tencentResp
if err := json.Unmarshal(resp.GetBody(), &r); err != nil {
return Result{}, fmt.Errorf("idverify/tencent: 响应解析失败: %w", err)
}
if e := r.Response.Error; e != nil && e.Code != "" {
return Result{}, fmt.Errorf("idverify/tencent: 调用返回错误 Code=%s Message=%s RequestId=%s", e.Code, e.Message, r.Response.RequestId)
}
switch r.Response.Result {
case tencentResultMatched:
return Result{Matched: true, BizCode: r.Response.Result, Message: r.Response.Description}, nil
case tencentResultMismatch:
return Result{Matched: false, BizCode: r.Response.Result, Message: r.Response.Description}, nil
default:
// -2..-7 是"查无此人/格式错误/当日超限/系统升级"等,结论未知,不能判成"不一致",
// 否则服务商当日额度用尽时,所有用户都会看到"信息有误"。
return Result{}, fmt.Errorf("idverify/tencent: 核验未得出结论 Result=%s Description=%s RequestId=%s",
r.Response.Result, r.Response.Description, r.Response.RequestId)
}
}