package handlers import ( "encoding/json" "fmt" "platform/pkg/env" "platform/pkg/u" "platform/web/auth" "platform/web/core" g "platform/web/globals" 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" ) // Identify 发起实名认证 func Identify(c *fiber.Ctx) error { // 检查权限 authCtx, err := auth.GetAuthCtx(c).PermitUser() if err != nil { return err } user := authCtx.User if user.IDToken != nil && *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 } if resp.Error.Code != 0 { var msg string switch resp.Error.Code { case 1007: msg = "身份证号码格式错误" } return core.NewBizErr(fmt.Sprintf("活体认证失败: %s", msg)) } // 保存认证中间状态 info := idenInfo{ Uid: user.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 = g.Redis.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, }) } type IdentifyReq struct { Type int `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"` } type idenResultData struct { Success bool Message string } // IdentifyCallbackNew 更新用户实名认证状态 func IdentifyCallbackNew(c *fiber.Ctx) error { // 解析请求参数 req := new(struct { Id string `json:"id" validate:"required"` Success bool `json:"success" validate:"required"` }) if err := c.QueryParser(req); err != nil { return renderIdenResult(c, false, "解析请求参数失败") } // 获取 token infoStr, err := g.Redis.GetDel(c.Context(), idenKey(req.Id)).Bytes() if err != nil { return renderIdenResult(c, false, "实名认证状态已失效,请重新发起认证") } info := idenInfo{} if err = json.Unmarshal(infoStr, &info); err != nil { return renderIdenResult(c, false, "解析实名认证信息失败,请重新发起认证") } // 获取认证结果 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 renderIdenResult(c, false, "获取实名认证结果失败,请重新发起认证") } if resp.Error.Code != 0 { return renderIdenResult(c, false, fmt.Sprintf("获取实名认证结果失败:%s", resp.Error.Message)) } if resp.Result.H5Result != "ok" || resp.Result.SmResult != "ok" || resp.Result.RxResult != "ok" { return renderIdenResult(c, false, fmt.Sprintf("实名认证未通过:%s", resp.Result.Desc)) } // 更新用户实名认证状态 _, err = q.User. Where(q.User.ID.Eq(info.Uid)). UpdateSimple( q.User.IDType.Value(info.Type), q.User.IDNo.Value(info.IdNo), q.User.Name.Value(info.Name), q.User.IDToken.Value(info.Token), ) if err != nil { return renderIdenResult(c, false, "保存实名认证信息失败,请联系客服处理") } // 返回结果页面 return renderIdenResult(c, true, "实名认证成功,请在扫码页面点击按钮完成认证") } func renderIdenResult(c *fiber.Ctx, success bool, message string) error { return c.Render("views/iden-result", idenResultData{ Success: success, Message: message, }) } // DebugIdentifyClear 清除用户实名认证状态(调试用) func DebugIdentifyClear(c *fiber.Ctx) error { phone := c.Params("phone") if phone == "" { return core.NewServErr("需要提供手机号") } _, err := q.User. Where( q.User.Phone.Eq(phone), ). UpdateSimple( q.User.IDType.Value(0), q.User.IDNo.Value(""), q.User.IDToken.Value(""), ) if err != nil { return core.NewServErr("清除实名认证失败") } return c.SendString("实名信息已清除") } func idenKey(id string) string { return fmt.Sprintf("iden:%s", id) } type idenInfo struct { Uid int32 `json:"uid"` Type int `json:"type"` Name string `json:"name"` IdNo string `json:"id_no"` Token string `json:"token"` }