feat: bind tribally account

This commit is contained in:
2025-03-20 17:15:54 +08:00
parent 3f09a65806
commit 937244a1a0
10 changed files with 202 additions and 0 deletions

View File

@@ -13,6 +13,7 @@ const (
KgenApiKey = "kgen_api_key"
AdminSecret = "admin_secret"
NftHolderApiConf = "nft_holder_api_conf"
TriballyApiKey = "tribally_api_key"
)
type AssetType string

View File

@@ -145,6 +145,12 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
[]rest.Route{
{
// 绑定Tribally账号
Method: http.MethodGet,
Path: "/bind_tribally",
Handler: task.BindTriballyHandler(serverCtx),
},
{
// 质押NFT
Method: http.MethodPost,

View File

@@ -0,0 +1,22 @@
package task
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"nova_task/internal/logic/task"
"nova_task/internal/svc"
)
// 绑定Tribally账号
func BindTriballyHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := task.NewBindTriballyLogic(r.Context(), svcCtx)
resp, err := l.BindTribally()
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}

View File

@@ -0,0 +1,64 @@
package task
import (
"context"
"errors"
"nova_task/internal/model"
"nova_task/internal/pkg/errs"
"nova_task/internal/pkg/tribally"
"nova_task/internal/pkg/utils"
"nova_task/internal/svc"
"nova_task/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type BindTriballyLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// 绑定Tribally账号
func NewBindTriballyLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BindTriballyLogic {
return &BindTriballyLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *BindTriballyLogic) BindTribally() (resp *types.BindTriballyReply, err error) {
uid := utils.GetUidUint(l.ctx)
apiKey, err := l.svcCtx.ConfigModel.GetTriballyApiKey(l.ctx)
if err != nil {
l.Errorw("get tribally api key failed", logx.Field("err", err))
return nil, errs.New(errs.ErrDatabaseOperate, err)
}
if apiKey == "" {
return nil, errs.New(errs.ErrSystemConfig, "system config err")
}
u, err := l.svcCtx.UserModel.FindOne(l.ctx, uid)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return nil, errs.New(errs.ErrUserNotFound, "user not found")
}
l.Errorw("get user failed", logx.Field("err", err), logx.Field("uid", uid))
return nil, errs.New(errs.ErrDatabaseOperate, err)
}
hasBind, err := l.svcCtx.RoleModel.AccountExist(l.ctx, u.Email)
if err != nil {
return nil, errs.New(errs.ErrDatabaseOperate, err)
}
if !hasBind {
return nil, errs.New(errs.ErrNotBindRole, "user not bind role")
}
authUrl, err := tribally.BindTribally(apiKey, u.Email)
if err != nil {
l.Errorw("bind tribally failed", logx.Field("err", err))
return nil, errs.New(errs.ErrInternalServer, err)
}
return &types.BindTriballyReply{AuthUrl: authUrl}, nil
}

View File

@@ -24,6 +24,7 @@ type (
GetApiKey(ctx context.Context, name string) (apiKey string, err error)
GetAdminSecret(ctx context.Context) (secret string, err error)
GetInviterId(ctx context.Context, name string) uint
GetTriballyApiKey(ctx context.Context) (apiKey string, err error)
}
customNhSystemConfigModel struct {
@@ -31,6 +32,17 @@ type (
}
)
func (m *customNhSystemConfigModel) GetTriballyApiKey(ctx context.Context) (apiKey string, err error) {
cf, err := m.FindOneByName(ctx, consts.TriballyApiKey)
if err != nil {
if !errors.Is(err, sqlx.ErrNotFound) {
return "", err
}
return "", nil
}
return cf.Value, nil
}
func (m *customNhSystemConfigModel) GetInviterId(ctx context.Context, name string) uint {
cf, err := m.FindOneByName(ctx, name)
if err != nil {

View File

@@ -16,6 +16,7 @@ const (
ErrEncodePassword Reason = 1003 // 密码加密错误
ErrGenerateUUid Reason = 1004 // 生成uuid错误
ErrGenerateToken Reason = 1005 // 生成token错误
ErrSystemConfig Reason = 1006 // 系统配置错误
// ======= 业务层错误20000~29999 =======
ErrUnknownLogicError Reason = 20000 // 未知的业务错误
@@ -30,4 +31,5 @@ const (
ErrInvalidApiKey Reason = 20009 // 无效的api key
ErrRoleNotFound Reason = 20010 // 角色不存在
ErrInvalidParam Reason = 20011 // 无效的参数
ErrNotBindRole Reason = 20012 // 未绑定角色
)

View File

@@ -0,0 +1,48 @@
package tribally
import (
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
)
func BindTribally(apiKey, userId string) (string, error) {
url := "https://api.tribally.games/authenticate"
payload := strings.NewReader(fmt.Sprintf(`{"playerId": "%s"}`, userId))
req, err := http.NewRequest(http.MethodPost, url, payload)
if err != nil {
return "", err
}
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Accept", "application/json")
req.Header.Add("x-api-key", apiKey)
res, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
return "", err
}
result := struct {
Error string `json:"error"`
Code string `json:"code"`
Data struct {
AuthURL string `json:"authUrl"`
} `json:"data"`
}{}
err = json.Unmarshal(body, &result)
if err != nil {
return "", err
}
if result.Error != "" {
return "", fmt.Errorf("error: %s, code: %s", result.Error, result.Code)
}
return result.Data.AuthURL, nil
}

View File

@@ -3,6 +3,10 @@
package types
type BindTriballyReply struct {
AuthUrl string `json:"auth_url"` // 授权地址
}
type CarvResult struct {
Result *Result `json:"result"`
Error *Error `json:"error"`