Refactor: Remove deprecated gRPC service files and implement new API structure

- Deleted old gRPC service definitions in `game_grpc.pb.go` and `public.go`.
- Added new API server implementations for objectstory, player, and shop services.
- Introduced configuration files for new APIs in `etc/*.yaml`.
- Created main entry points for each service in `objectstory.go`, `player.go`, and `shop.go`.
- Removed unused user update handler and user API files.
- Added utility functions for context management and HTTP header parsing.
- Introduced PostgreSQL backup configuration in `backup/postgreSql.yaml`.
This commit is contained in:
wwweww
2026-02-28 18:35:56 +08:00
parent d2f33b4b96
commit 19cc7a778c
349 changed files with 42548 additions and 1453 deletions
+14
View File
@@ -0,0 +1,14 @@
// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2
package config
import (
"github.com/zeromicro/go-zero/rest"
"github.com/zeromicro/go-zero/zrpc"
)
type Config struct {
rest.RestConf
WalletRpcConf zrpc.RpcClientConf
}
+45
View File
@@ -0,0 +1,45 @@
// Code generated by goctl. DO NOT EDIT.
// goctl 1.9.2
package handler
import (
"net/http"
wallet "juwan-backend/app/wallet/api/internal/handler/wallet"
"juwan-backend/app/wallet/api/internal/svc"
"github.com/zeromicro/go-zero/rest"
)
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
[]rest.Route{
{
// 获取余额
Method: http.MethodGet,
Path: "/balance",
Handler: wallet.GetBalanceHandler(serverCtx),
},
{
// 充值
Method: http.MethodPost,
Path: "/topup",
Handler: wallet.TopupHandler(serverCtx),
},
{
// 获取流水
Method: http.MethodGet,
Path: "/transactions",
Handler: wallet.ListTransactionsHandler(serverCtx),
},
{
// 提现
Method: http.MethodPost,
Path: "/withdraw",
Handler: wallet.WithdrawHandler(serverCtx),
},
},
rest.WithPrefix("/api/v1/wallet"),
)
}
@@ -0,0 +1,32 @@
// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2
package wallet
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"juwan-backend/app/wallet/api/internal/logic/wallet"
"juwan-backend/app/wallet/api/internal/svc"
"juwan-backend/app/wallet/api/internal/types"
)
// 获取余额
func GetBalanceHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.EmptyResp
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := wallet.NewGetBalanceLogic(r.Context(), svcCtx)
resp, err := l.GetBalance(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}
@@ -0,0 +1,32 @@
// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2
package wallet
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"juwan-backend/app/wallet/api/internal/logic/wallet"
"juwan-backend/app/wallet/api/internal/svc"
"juwan-backend/app/wallet/api/internal/types"
)
// 获取流水
func ListTransactionsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.PageReq
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := wallet.NewListTransactionsLogic(r.Context(), svcCtx)
resp, err := l.ListTransactions(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}
@@ -0,0 +1,32 @@
// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2
package wallet
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"juwan-backend/app/wallet/api/internal/logic/wallet"
"juwan-backend/app/wallet/api/internal/svc"
"juwan-backend/app/wallet/api/internal/types"
)
// 充值
func TopupHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.TopupReq
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := wallet.NewTopupLogic(r.Context(), svcCtx)
resp, err := l.Topup(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}
@@ -0,0 +1,32 @@
// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2
package wallet
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"juwan-backend/app/wallet/api/internal/logic/wallet"
"juwan-backend/app/wallet/api/internal/svc"
"juwan-backend/app/wallet/api/internal/types"
)
// 提现
func WithdrawHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.TopupReq
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := wallet.NewWithdrawLogic(r.Context(), svcCtx)
resp, err := l.Withdraw(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}
@@ -0,0 +1,52 @@
// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2
package wallet
import (
"context"
"juwan-backend/app/wallet/rpc/pb"
"juwan-backend/common/utils/contextj"
"juwan-backend/app/wallet/api/internal/svc"
"juwan-backend/app/wallet/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetBalanceLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// 获取余额
func NewGetBalanceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetBalanceLogic {
return &GetBalanceLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetBalanceLogic) GetBalance(req *types.EmptyResp) (resp *types.WalletBalance, err error) {
userID, err := contextj.UserIDFrom(l.ctx)
if err != nil {
return nil, err
}
out, err := l.svcCtx.WalletRpc.GetWalletsById(l.ctx, &pb.GetWalletsByIdReq{Id: userID})
if err != nil {
return nil, err
}
if out.GetWallets() == nil {
return &types.WalletBalance{Balance: "0", FrozenBalance: "0"}, nil
}
return &types.WalletBalance{
Balance: out.Wallets.Balance,
FrozenBalance: out.Wallets.FrozenBalance,
}, nil
}
@@ -0,0 +1,80 @@
// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2
package wallet
import (
"context"
"strconv"
"time"
"juwan-backend/app/wallet/rpc/pb"
"juwan-backend/common/utils/contextj"
"juwan-backend/app/wallet/api/internal/svc"
"juwan-backend/app/wallet/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type ListTransactionsLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// 获取流水
func NewListTransactionsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListTransactionsLogic {
return &ListTransactionsLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *ListTransactionsLogic) ListTransactions(req *types.PageReq) (resp *types.TransactionListResp, err error) {
userID, err := contextj.UserIDFrom(l.ctx)
if err != nil {
return nil, err
}
if req.Limit <= 0 {
req.Limit = 20
}
out, err := l.svcCtx.WalletRpc.SearchWalletTransactions(l.ctx, &pb.SearchWalletTransactionsReq{
Page: req.Offset / req.Limit,
Limit: req.Limit,
UserId: &userID,
})
if err != nil {
return nil, err
}
items := make([]types.Transaction, 0, len(out.GetWalletTransactions()))
for _, item := range out.GetWalletTransactions() {
if item == nil {
continue
}
tx := types.Transaction{
Id: item.Id,
Type: item.Type,
Amount: item.Amount,
Description: item.Description,
CreatedAt: time.Unix(item.CreatedAt, 0).Format(time.RFC3339),
}
if item.OrderId > 0 {
tx.OrderId = strconv.FormatInt(item.OrderId, 10)
}
items = append(items, tx)
}
return &types.TransactionListResp{
Items: items,
Meta: types.PageMeta{
Total: int64(len(items)),
Offset: req.Offset,
Limit: req.Limit,
},
}, nil
}
@@ -0,0 +1,127 @@
// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2
package wallet
import (
"context"
"errors"
"fmt"
"time"
"juwan-backend/app/wallet/rpc/pb"
"juwan-backend/common/utils/contextj"
"juwan-backend/app/wallet/api/internal/svc"
"juwan-backend/app/wallet/api/internal/types"
"github.com/shopspring/decimal"
"github.com/zeromicro/go-zero/core/logx"
)
type TopupLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// 充值
func NewTopupLogic(ctx context.Context, svcCtx *svc.ServiceContext) *TopupLogic {
return &TopupLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *TopupLogic) Topup(req *types.TopupReq) (resp *types.EmptyResp, err error) {
amount, err := decimal.NewFromString(req.Amount)
if err != nil {
return nil, errors.New("invalid amount")
}
if !amount.GreaterThan(decimal.Zero) {
return nil, errors.New("amount must be greater than 0")
}
userID, err := contextj.UserIDFrom(l.ctx)
if err != nil {
return nil, err
}
walletResp, err := l.svcCtx.WalletRpc.GetWalletsById(l.ctx, &pb.GetWalletsByIdReq{Id: userID})
if err != nil {
return nil, err
}
currentBalance := decimal.Zero
frozenBalance := decimal.Zero
expectedVersion := int64(0)
if walletResp.GetWallets() == nil {
zeroAmount := "0"
_, err = l.svcCtx.WalletRpc.AddWallets(l.ctx, &pb.AddWalletsReq{
UserId: userID,
Balance: zeroAmount,
FrozenBalance: zeroAmount,
UpdatedAt: time.Now().Unix(),
})
if err != nil {
return nil, err
}
walletResp, err = l.svcCtx.WalletRpc.GetWalletsById(l.ctx, &pb.GetWalletsByIdReq{Id: userID})
if err != nil {
return nil, err
}
if walletResp.GetWallets() == nil {
return nil, errors.New("wallet not found")
}
currentBalance, err = decimal.NewFromString(walletResp.Wallets.Balance)
if err != nil {
return nil, errors.New("invalid wallet balance")
}
frozenBalance, err = decimal.NewFromString(walletResp.Wallets.FrozenBalance)
if err != nil {
return nil, errors.New("invalid wallet frozen balance")
}
expectedVersion = walletResp.Wallets.Version
} else {
currentBalance, err = decimal.NewFromString(walletResp.Wallets.Balance)
if err != nil {
return nil, errors.New("invalid wallet balance")
}
frozenBalance, err = decimal.NewFromString(walletResp.Wallets.FrozenBalance)
if err != nil {
return nil, errors.New("invalid wallet frozen balance")
}
expectedVersion = walletResp.Wallets.Version
}
newBalance := currentBalance.Add(amount)
newBalanceStr := newBalance.String()
frozenBalanceStr := frozenBalance.String()
updatedAt := time.Now().Unix()
_, err = l.svcCtx.WalletRpc.UpdateWallets(l.ctx, &pb.UpdateWalletsReq{
UserId: userID,
Balance: &newBalanceStr,
FrozenBalance: &frozenBalanceStr,
UpdatedAt: &updatedAt,
Version: &expectedVersion,
})
if err != nil {
return nil, err
}
desc := fmt.Sprintf("topup via %s", req.Method)
_, err = l.svcCtx.WalletRpc.AddWalletTransactions(l.ctx, &pb.AddWalletTransactionsReq{
UserId: userID,
Type: "topup",
Amount: amount.String(),
BalanceAfter: newBalanceStr,
Description: desc,
CreatedAt: updatedAt,
})
if err != nil {
return nil, err
}
return &types.EmptyResp{}, nil
}
@@ -0,0 +1,101 @@
// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2
package wallet
import (
"context"
"errors"
"fmt"
"time"
"juwan-backend/app/wallet/rpc/pb"
"juwan-backend/common/utils/contextj"
"juwan-backend/app/wallet/api/internal/svc"
"juwan-backend/app/wallet/api/internal/types"
"github.com/shopspring/decimal"
"github.com/zeromicro/go-zero/core/logx"
)
type WithdrawLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// 提现
func NewWithdrawLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WithdrawLogic {
return &WithdrawLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *WithdrawLogic) Withdraw(req *types.TopupReq) (resp *types.EmptyResp, err error) {
amount, err := decimal.NewFromString(req.Amount)
if err != nil {
return nil, errors.New("invalid amount")
}
if !amount.GreaterThan(decimal.Zero) {
return nil, errors.New("amount must be greater than 0")
}
userID, err := contextj.UserIDFrom(l.ctx)
if err != nil {
return nil, err
}
walletResp, err := l.svcCtx.WalletRpc.GetWalletsById(l.ctx, &pb.GetWalletsByIdReq{Id: userID})
if err != nil {
return nil, err
}
if walletResp.GetWallets() == nil {
return nil, errors.New("wallet not found")
}
currentBalance, err := decimal.NewFromString(walletResp.Wallets.Balance)
if err != nil {
return nil, errors.New("invalid wallet balance")
}
frozenBalance, err := decimal.NewFromString(walletResp.Wallets.FrozenBalance)
if err != nil {
return nil, errors.New("invalid wallet frozen balance")
}
expectedVersion := walletResp.Wallets.Version
if currentBalance.LessThan(amount) {
return nil, errors.New("insufficient balance")
}
newBalance := currentBalance.Sub(amount)
newBalanceStr := newBalance.String()
frozenBalanceStr := frozenBalance.String()
updatedAt := time.Now().Unix()
_, err = l.svcCtx.WalletRpc.UpdateWallets(l.ctx, &pb.UpdateWalletsReq{
UserId: userID,
Balance: &newBalanceStr,
FrozenBalance: &frozenBalanceStr,
UpdatedAt: &updatedAt,
Version: &expectedVersion,
})
if err != nil {
return nil, err
}
desc := fmt.Sprintf("withdraw via %s", req.Method)
_, err = l.svcCtx.WalletRpc.AddWalletTransactions(l.ctx, &pb.AddWalletTransactionsReq{
UserId: userID,
Type: "withdrawal",
Amount: amount.String(),
BalanceAfter: newBalanceStr,
Description: desc,
CreatedAt: updatedAt,
})
if err != nil {
return nil, err
}
return &types.EmptyResp{}, nil
}
@@ -0,0 +1,23 @@
// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2
package svc
import (
"juwan-backend/app/wallet/api/internal/config"
"juwan-backend/app/wallet/rpc/walletservice"
"github.com/zeromicro/go-zero/zrpc"
)
type ServiceContext struct {
Config config.Config
WalletRpc walletservice.WalletService
}
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
WalletRpc: walletservice.NewWalletService(zrpc.MustNewClient(c.WalletRpcConf)),
}
}
+61
View File
@@ -0,0 +1,61 @@
// Code generated by goctl. DO NOT EDIT.
// goctl 1.9.2
package types
type EmptyResp struct {
}
type PageMeta struct {
Total int64 `json:"total"`
Offset int64 `json:"offset"`
Limit int64 `json:"limit"`
}
type PageReq struct {
Offset int64 `form:"offset,default=0"`
Limit int64 `form:"limit,default=20"`
}
type SimpleUser struct {
Id string `json:"id"`
Nickname string `json:"nickname"`
Avatar string `json:"avatar"`
}
type TopupReq struct {
Amount string `json:"amount"`
Method string `json:"method"`
}
type Transaction struct {
Id int64 `json:"id"`
Type string `json:"type"`
Amount string `json:"amount"`
Description string `json:"description"`
OrderId string `json:"orderId,optional"`
CreatedAt string `json:"createdAt"`
}
type TransactionListResp struct {
Items []Transaction `json:"items"`
Meta PageMeta `json:"meta"`
}
type UserProfile struct {
Id string `json:"id"`
Username string `json:"username"`
Nickname string `json:"nickname"`
Avatar string `json:"avatar"`
Role string `json:"role"` // consumer, player, owner, admin
VerifiedRoles []string `json:"verifiedRoles"`
VerificationStatus map[string]string `json:"verificationStatus"`
Phone string `json:"phone,optional"`
Bio string `json:"bio,optional"`
CreatedAt string `json:"createdAt"`
}
type WalletBalance struct {
Balance string `json:"balance"`
FrozenBalance string `json:"frozenBalance"`
}