feat: bind tribally account
This commit is contained in:
@@ -51,6 +51,10 @@ service novatask {
|
|||||||
@doc "赛季奖励数据"
|
@doc "赛季奖励数据"
|
||||||
@handler PioneerReward
|
@handler PioneerReward
|
||||||
get /pioneer_reward returns (PioneerReward)
|
get /pioneer_reward returns (PioneerReward)
|
||||||
|
|
||||||
|
@doc "绑定Tribally账号"
|
||||||
|
@handler BindTribally
|
||||||
|
get /bind_tribally returns (BindTriballyReply)
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetTaskListReq {
|
type GetTaskListReq {
|
||||||
@@ -168,3 +172,7 @@ type PioneerReward {
|
|||||||
Total float64 `json:"total"` // 总额
|
Total float64 `json:"total"` // 总额
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BindTriballyReply {
|
||||||
|
AuthUrl string `json:"auth_url"` // 授权地址
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -437,6 +437,28 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/gapi/task/v1/bind_tribally": {
|
||||||
|
"get": {
|
||||||
|
"summary": "绑定Tribally账号",
|
||||||
|
"operationId": "BindTribally",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A successful response.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/BindTriballyReply"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"task"
|
||||||
|
],
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"apiKey": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/gapi/task/v1/community": {
|
"/gapi/task/v1/community": {
|
||||||
"get": {
|
"get": {
|
||||||
"summary": "获取社区列表",
|
"summary": "获取社区列表",
|
||||||
@@ -732,6 +754,19 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
|
"BindTriballyReply": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"auth_url": {
|
||||||
|
"type": "string",
|
||||||
|
"description": " 授权地址"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": "BindTriballyReply",
|
||||||
|
"required": [
|
||||||
|
"auth_url"
|
||||||
|
]
|
||||||
|
},
|
||||||
"CarvResult": {
|
"CarvResult": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ const (
|
|||||||
KgenApiKey = "kgen_api_key"
|
KgenApiKey = "kgen_api_key"
|
||||||
AdminSecret = "admin_secret"
|
AdminSecret = "admin_secret"
|
||||||
NftHolderApiConf = "nft_holder_api_conf"
|
NftHolderApiConf = "nft_holder_api_conf"
|
||||||
|
TriballyApiKey = "tribally_api_key"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AssetType string
|
type AssetType string
|
||||||
|
|||||||
@@ -145,6 +145,12 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
|
|
||||||
server.AddRoutes(
|
server.AddRoutes(
|
||||||
[]rest.Route{
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
// 绑定Tribally账号
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/bind_tribally",
|
||||||
|
Handler: task.BindTriballyHandler(serverCtx),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
// 质押NFT
|
// 质押NFT
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
|
|||||||
22
internal/handler/task/bind_tribally_handler.go
Normal file
22
internal/handler/task/bind_tribally_handler.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
64
internal/logic/task/bind_tribally_logic.go
Normal file
64
internal/logic/task/bind_tribally_logic.go
Normal 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
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@ type (
|
|||||||
GetApiKey(ctx context.Context, name string) (apiKey string, err error)
|
GetApiKey(ctx context.Context, name string) (apiKey string, err error)
|
||||||
GetAdminSecret(ctx context.Context) (secret string, err error)
|
GetAdminSecret(ctx context.Context) (secret string, err error)
|
||||||
GetInviterId(ctx context.Context, name string) uint
|
GetInviterId(ctx context.Context, name string) uint
|
||||||
|
GetTriballyApiKey(ctx context.Context) (apiKey string, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
customNhSystemConfigModel struct {
|
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 {
|
func (m *customNhSystemConfigModel) GetInviterId(ctx context.Context, name string) uint {
|
||||||
cf, err := m.FindOneByName(ctx, name)
|
cf, err := m.FindOneByName(ctx, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ const (
|
|||||||
ErrEncodePassword Reason = 1003 // 密码加密错误
|
ErrEncodePassword Reason = 1003 // 密码加密错误
|
||||||
ErrGenerateUUid Reason = 1004 // 生成uuid错误
|
ErrGenerateUUid Reason = 1004 // 生成uuid错误
|
||||||
ErrGenerateToken Reason = 1005 // 生成token错误
|
ErrGenerateToken Reason = 1005 // 生成token错误
|
||||||
|
ErrSystemConfig Reason = 1006 // 系统配置错误
|
||||||
|
|
||||||
// ======= 业务层错误:20000~29999 =======
|
// ======= 业务层错误:20000~29999 =======
|
||||||
ErrUnknownLogicError Reason = 20000 // 未知的业务错误
|
ErrUnknownLogicError Reason = 20000 // 未知的业务错误
|
||||||
@@ -30,4 +31,5 @@ const (
|
|||||||
ErrInvalidApiKey Reason = 20009 // 无效的api key
|
ErrInvalidApiKey Reason = 20009 // 无效的api key
|
||||||
ErrRoleNotFound Reason = 20010 // 角色不存在
|
ErrRoleNotFound Reason = 20010 // 角色不存在
|
||||||
ErrInvalidParam Reason = 20011 // 无效的参数
|
ErrInvalidParam Reason = 20011 // 无效的参数
|
||||||
|
ErrNotBindRole Reason = 20012 // 未绑定角色
|
||||||
)
|
)
|
||||||
|
|||||||
48
internal/pkg/tribally/tribally.go
Normal file
48
internal/pkg/tribally/tribally.go
Normal 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
|
||||||
|
}
|
||||||
@@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
package types
|
package types
|
||||||
|
|
||||||
|
type BindTriballyReply struct {
|
||||||
|
AuthUrl string `json:"auth_url"` // 授权地址
|
||||||
|
}
|
||||||
|
|
||||||
type CarvResult struct {
|
type CarvResult struct {
|
||||||
Result *Result `json:"result"`
|
Result *Result `json:"result"`
|
||||||
Error *Error `json:"error"`
|
Error *Error `json:"error"`
|
||||||
|
|||||||
Reference in New Issue
Block a user