Files
platform/web/handlers/iden.go

206 lines
4.2 KiB
Go

package handlers
import (
"encoding/json"
"errors"
"fmt"
"platform/pkg/env"
"platform/pkg/u"
"platform/web/auth"
g "platform/web/globals"
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 = 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,
})
}
// 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 := g.Redis.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 = g.Redis.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"`
}