From 2f35803893af5b27730fb947c50537ca35e3bbe9 Mon Sep 17 00:00:00 2001 From: xuyang Date: Sat, 9 May 2026 12:23:34 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=A2=84=E4=B8=8B=E5=8D=95?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + CLAUDE.md | 134 +++++++++++++++++++++++++++++++++++ services/game/client.go | 7 ++ services/game/client_test.go | 27 +++++++ services/game/pay.go | 64 +++++++++++++++++ 5 files changed, 233 insertions(+) create mode 100644 CLAUDE.md diff --git a/.gitignore b/.gitignore index 173454b..99cd473 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ *.iml out gen +.claude diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..1c33004 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,134 @@ +# CLAUDE.md + +本文件为 Claude Code (claude.ai/code) 在此仓库中工作时提供指引。 + +## 常用命令 + +```bash +# 运行某个 service 的全部测试 +go test ./services/apk/... + +# 运行单个测试函数 +go test ./services/apk/... -run TestClient_GetUserInfo -v + +# 编译检查 +go build ./... +``` + +## 整体架构 + +分两层: + +- `sdk/`:核心框架,处理签名、HTTP 请求、响应解析,不含业务逻辑 +- `services//`:各业务服务封装,每个包是一个独立 SDK client + +### sdk/ 核心流程 + +``` +调用方 → Client.DoAction(req, resp) + → auth.Sign(req, signer) # 根据 credential 类型签名 + → req.BuildUrl() # RpcRequest 拼接域名+路径+query + → HTTP 请求 + → responses.Unmarshal(resp) # JSON 反序列化 +``` + +- `sdk/auth/credentials/`:三种凭证类型(AccessKey、StsToken、AliAppcode) +- `sdk/auth/signers/`:对应签名器实现 +- `sdk/requests/`:`RpcRequest`(主流)和 `RoaRequest` 两种请求风格;字段通过 struct tag `position:"Body|Query|Header"` 和 `field:"xxx"` 声明参数位置 +- `sdk/config.go`:`Config` 结构体,字段用 `default:"..."` tag 自动初始化 + +### services/ 统一模式 + +每个服务包含: + +| 文件 | 职责 | +|------|------| +| `client.go` | 定义 `Client`(内嵌 `sdk.Client`)、`HOST`、`VERSION` 常量,以及所有对外方法 | +| `xxx_action.go` | 每个接口一个文件,包含 Request/Response 结构体和两个工厂函数 | + +## 添加新接口的标准步骤 + +**1. 新建 `services//new_action.go`:** + +```go +package + +import ( + "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/requests" + "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/responses" +) + +type NewActionRequest struct { + *requests.RpcRequest + Field1 string `position:"Body" field:"field1" default:""` + Field2 int64 `position:"Body" field:"field2"` +} + +type NewActionResponse struct { + *responses.BaseResponse + Code int `json:"code"` + Msg string `json:"msg"` + Data struct { + // ... + } `json:"data"` +} + +func CreateNewActionRequest() *NewActionRequest { + req := &NewActionRequest{RpcRequest: &requests.RpcRequest{}} + req.InitWithApiInfo(HOST, VERSION, "/api/path/here") + req.Method = requests.POST + return req +} + +func CreateNewActionResponse() *NewActionResponse { + return &NewActionResponse{BaseResponse: &responses.BaseResponse{}} +} +``` + +**2. 在 `client.go` 添加方法:** + +```go +func (c *Client) NewAction(req *NewActionRequest) (response *NewActionResponse, err error) { + response = CreateNewActionResponse() + err = c.DoAction(req, response) + return +} +``` + +## HOST 两种写法 + +```go +// 简单写法(内部服务,hostname 由调用方注入) +var HOST = requests.Host{Default: "service-name"} + +// 带环境路由写法(外部服务,各环境域名不同) +var HOST = requests.Host{ + Default: "api.example.com", + Func: func(env string) string { + return map[string]string{ + requests.RELEASE: "api.example.com", + requests.TEST: "test.api.example.com", + }[env] + }, +} +``` + +环境常量:`requests.RELEASE`、`requests.PRE`、`requests.TEST` + +## Client 初始化两种模式 + +```go +// 模式一:无需认证(apk、callback 等内部服务) +func NewClient() *Client { + client := &Client{} + client.InitWithAccessKey("", "", "") + return client +} + +// 模式二:需要认证(sso、pay 等) +func NewClient() (*Client, error) { + client := new(Client) + err := client.Init() + return client, err +} +``` diff --git a/services/game/client.go b/services/game/client.go index b2c72ea..52ffd49 100644 --- a/services/game/client.go +++ b/services/game/client.go @@ -191,3 +191,10 @@ func (c *Client) GetGameListExtInfo(req *GetGameListExtInfoReq) (response *GetGa err = c.DoAction(req, response) return } + +// MakeOrder 预下单(线下支付) +func (c *Client) MakeOrder(req *MakeOrderReq) (response *MakeOrderResp, err error) { + response = CreateMakeOrderResp() + err = c.DoAction(req, response) + return +} diff --git a/services/game/client_test.go b/services/game/client_test.go index 313b1bd..b017c20 100644 --- a/services/game/client_test.go +++ b/services/game/client_test.go @@ -383,3 +383,30 @@ func TestGetActivityVipUserNewBlacklist(t *testing.T) { fmt.Printf("%#+v\n", *resp.Data) } } + +func TestCreateMakeOrderReq(t *testing.T) { + req := CreateMakeOrderReq(MakeOrderParam{ + Username: "vd22543241", + Gid: 123, + Sid: "123", + RealSid: "123", + RoleId: "123", + RoleName: "13", + Money: 6, + ServerName: "333", + ProductName: "666", + DwId: 666, + }) + + client, err := NewClient() + if err != nil { + t.Error(err) + return + } + resp, err := client.MakeOrder(req) + if err != nil { + t.Error(err) + return + } + fmt.Println(resp.Msg) +} diff --git a/services/game/pay.go b/services/game/pay.go index f938f0b..5f97dae 100644 --- a/services/game/pay.go +++ b/services/game/pay.go @@ -58,3 +58,67 @@ func CreateIsBlockOutIosResp() *IsBlockOutIosResp { } return resp } + +// MakeOrderReq 预下单请求 +type MakeOrderReq struct { + *requests.RpcRequest + Username string `position:"Body" field:"username"` + Gid int64 `position:"Body" field:"gid"` + Sid string `position:"Body" field:"sid"` + RealSid string `position:"Body" field:"real_sid"` + RoleId string `position:"Body" field:"role_id"` + RoleName string `position:"Body" field:"role_name"` + Money float64 `position:"Body" field:"money"` + ServerName string `position:"Body" field:"server_name"` + ProductName string `position:"Body" field:"product_name"` + DwId int64 `position:"Body" field:"dw_id"` +} + +type MakeOrderRespData struct { + OrderID string `json:"orderID"` +} + +type MakeOrderResp struct { + *responses.BaseResponse + Code int `json:"code"` + Msg string `json:"msg"` + Data MakeOrderRespData `json:"data"` +} + +type MakeOrderParam struct { + Username string + Gid int64 + Sid string + RealSid string + RoleId string + RoleName string + Money float64 + ServerName string + ProductName string + DwId int64 +} + +func CreateMakeOrderReq(param MakeOrderParam) *MakeOrderReq { + req := &MakeOrderReq{ + RpcRequest: &requests.RpcRequest{}, + Username: param.Username, + Gid: param.Gid, + Sid: param.Sid, + RealSid: param.RealSid, + RoleId: param.RoleId, + RoleName: param.RoleName, + Money: param.Money, + ServerName: param.ServerName, + ProductName: param.ProductName, + DwId: param.DwId, + } + req.InitWithApiInfo(HOST, VERSION, "/api/pay/makeOrder") + req.Method = requests.POST + return req +} + +func CreateMakeOrderResp() *MakeOrderResp { + return &MakeOrderResp{ + BaseResponse: &responses.BaseResponse{}, + } +}