package handlers import ( "encoding/json" "errors" "fmt" "platform/pkg/env" "platform/pkg/rds" "platform/pkg/u" "platform/web/auth" m "platform/web/models" q "platform/web/queries" "platform/web/services" "time" "github.com/gofiber/fiber/v2" jdc "github.com/jdcloud-api/jdcloud-sdk-go/core" "github.com/jdcloud-api/jdcloud-sdk-go/services/cloudauth/apis" jdclient "github.com/jdcloud-api/jdcloud-sdk-go/services/cloudauth/client" "github.com/redis/go-redis/v9" ) // region Identify type IdentifyReq struct { Type int32 `json:"type" validate:"required,oneof=1 2"` Name string `json:"name" validate:"required"` IdenNo string `json:"iden_no" validate:"required"` } type IdentifyRes struct { Identified bool `json:"identified"` Target string `json:"target"` } func Identify(c *fiber.Ctx) error { // 检查权限 authCtx, err := auth.Protect(c, []auth.PayloadType{auth.PayloadUser}, []string{}) if err != nil { return err } user, err := q.User. Where(q.User.ID.Eq(authCtx.Payload.Id)). Select(q.User.ID, q.User.IDToken). Take() if err != nil { return err } if user.IDToken != "" { // 用户已实名认证 return c.JSON(IdentifyRes{ Identified: true, }) } // 解析请求参数 req := new(IdentifyReq) if err := c.BodyParser(req); err != nil { return err } // 请求活体认证 var id = services.ID.GenReadable("iden") var credential = jdc.NewCredentials(env.IdenAccessKey, env.IdenSecretKey) var client = jdclient.NewCloudauthClient(credential) resp, err := client.GetAliveUrl(apis.NewGetAliveUrlRequestWithAllParams( u.P(req.Name), u.P(req.IdenNo), env.IdenCallbackUrl+"?id="+id, )) if err != nil { return err } // 保存认证中间状态 info := idenInfo{ Uid: authCtx.Payload.Id, Type: req.Type, Name: req.Name, IdNo: req.IdenNo, Token: resp.Result.Token, } infoStr, err := json.Marshal(info) if err != nil { return err } err = rds.Client.Set(c.Context(), idenKey(id), infoStr, 30*time.Minute).Err() if err != nil { return err } return c.JSON(IdentifyRes{ Identified: false, Target: resp.Result.Url, }) } // endregion // region IdentifyCallback type IdentifyCallbackReq struct { Id string `json:"id" validate:"required"` } type IdentifyCallbackRes struct { Success bool `json:"success"` Message string `json:"desc"` } func IdentifyCallback(c *fiber.Ctx) error { // 解析请求参数 req := new(IdentifyCallbackReq) if err := c.BodyParser(req); err != nil { return err } // 获取 token infoStr, err := rds.Client.Get(c.Context(), idenKey(req.Id)).Result() if err != nil { if errors.Is(err, redis.Nil) { return c.JSON(IdentifyCallbackRes{ Success: true, Message: "认证已完成", }) } return err } info := idenInfo{} err = json.Unmarshal([]byte(infoStr), &info) if err != nil { return err } // 获取认证结果 var credential = jdc.NewCredentials(env.IdenAccessKey, env.IdenSecretKey) var client = jdclient.NewCloudauthClient(credential) resp, err := client.GetAliveResult(apis.NewGetAliveResultRequestWithAllParams( info.Token, )) if err != nil { return err } if resp.Error.Code != 0 { return c.JSON(IdentifyCallbackRes{ Success: false, Message: resp.Error.Message, }) } if resp.Result.H5Result != "ok" || resp.Result.SmResult != "ok" || resp.Result.RxResult != "ok" { return c.JSON(IdentifyCallbackRes{ Success: false, Message: resp.Result.Desc, }) } // 更新用户实名认证状态 _, err = q.User.Debug(). Where(q.User.ID.Eq(info.Uid)). Select( q.User.IDType, q.User.IDNo, q.User.IDToken, q.User.Name, ). Updates(m.User{ IDType: info.Type, IDNo: info.IdNo, IDToken: info.Token, Name: info.Name, }) if err != nil { return err } // 删除认证中间状态 err = rds.Client.Del(c.Context(), idenKey(req.Id)).Err() if err != nil { return err } return c.JSON(IdentifyCallbackRes{ Success: true, Message: resp.Result.Desc, }) } // endregion func idenKey(id string) string { return fmt.Sprintf("iden:%s", id) } type idenInfo struct { Uid int32 `json:"uid"` Type int32 `json:"type"` Name string `json:"name"` IdNo string `json:"id_no"` Token string `json:"token"` }