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
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)
|
|
}
|
|
}
|
|
|