本文档面向后续将 www/new_sdk/application/api 迁移到 Go 的落地设计,重点是模块边界、接口抽象、迁移顺序和风险控制。
cmd/
api/
main.go
internal/
bootstrap/ # 配置、DB、Redis、日志、依赖装配
config/ # app、game、payment、complex、third-party 配置
http/
router/ # 路由注册
middleware/ # 协议解密、鉴权、会话、限流、日志
handler/ # HTTP controller,保持薄层
response/ # 统一响应、错误码、SDK 加密输出
protocol/
codec/ # AES/JSON/兼容 imeil 等字段
sign/ # MD5 sign、appid/key 校验
token/ # auth_code/session token 编解码
domain/
account/ # 登录、注册、账号绑定、实名
session/ # token、Redis 会话
game/ # 游戏、区服、角色、版本、开服表
payment/ # 订单、支付渠道、回调、平台币
complex/ # 联运/渠道适配器
coupon/ # 优惠券
gift/ # 礼包、福利、客服中心
mlbb/ # MLBB 独立协议
thirdparty/ # 对外数据 API
repository/ # MySQL 仓储
integration/
payment/ # ali、wx、yunshanfu、dinpay、shande 等
identity/ # 实名、未成年、防沉迷
notify/ # CP 通知、钉钉告警
dataapi/ # dy、yql 等外部接口
pkg/
decimal/ # 金额处理封装,避免 float 误差
原则:HTTP 层只负责协议、参数和响应;业务规则沉到 domain service;MySQL/Redis 访问全部经 repository;第三方接口全部经 integration。
当前 controller\Api 承担了请求解密、签名、应用校验、返回加密、登录校验等多种职责。Go 版本建议拆成以下中间件:
RequestIDMiddleware
RecoverMiddleware
AccessLogMiddleware
SDKCodecMiddleware # AES-128-ECB 解密 data、兼容 imeil、响应加密
AppAuthMiddleware # appid、AppKey、MD5 sign 校验
SessionMiddleware # auth_code/token 解析、Redis 会话校验
RateLimitMiddleware # 按 appid、ip、用户或接口限流
保留兼容点:
imeil 这类历史字段不要迁移时强行改名,可在 Go 内部归一成 imei。type Codec interface {
DecodeRequest(ctx context.Context, req *http.Request) (*SDKRequest, error)
EncodeResponse(ctx context.Context, app AppConfig, body any) (*SDKResponse, error)
}
type Signer interface {
Verify(params map[string]string, appKey string, sign string) error
}
type SessionVerifier interface {
Verify(ctx context.Context, authCode string) (*Session, error)
Issue(ctx context.Context, userID int64, appID string) (*Session, error)
Revoke(ctx context.Context, authCode string) error
}
type AccountService interface {
Login(ctx context.Context, cmd LoginCommand) (*LoginResult, error)
Register(ctx context.Context, cmd RegisterCommand) (*RegisterResult, error)
QuickRegister(ctx context.Context, cmd QuickRegisterCommand) (*RegisterResult, error)
BindAccount(ctx context.Context, cmd BindAccountCommand) error
ChangePassword(ctx context.Context, cmd ChangePasswordCommand) error
SubmitIdentity(ctx context.Context, cmd IdentityCommand) (*IdentityResult, error)
}
账号迁移要特别关注同一用户在 Member、User、token、实名、防沉迷、渠道用户标识之间的映射关系。
type PaymentProvider interface {
CreatePayment(ctx context.Context, order PaymentOrder) (*PaymentIntent, error)
VerifyNotify(ctx context.Context, req NotifyRequest) (*NormalizedNotify, error)
SuccessResponse() HTTPResponse
FailResponse(reason string) HTTPResponse
}
type OrderService interface {
CreateGameOrder(ctx context.Context, cmd CreateOrderCommand) (*PaymentOrder, error)
MarkPaid(ctx context.Context, notify NormalizedNotify) (*PaymentOrder, error)
Cancel(ctx context.Context, orderNo string) error
GetOrder(ctx context.Context, orderNo string) (*PaymentOrder, error)
ListOrders(ctx context.Context, query OrderQuery) ([]PaymentOrder, error)
}
支付状态机建议固定为:
created -> paying -> paid -> delivering -> delivered
created -> canceled
paid/delivering -> deliver_failed -> delivering -> delivered
回调处理必须满足:
order_no 或第三方交易号做幂等。type ComplexAdapter interface {
Channel() string
CheckLogin(ctx context.Context, cmd ComplexLoginCommand, cfg ComplexGameConfig) (*ComplexLoginResult, error)
VerifyPayNotify(ctx context.Context, req ComplexNotifyRequest, cfg ComplexGameConfig) (*NormalizedComplexNotify, error)
SuccessResponse() HTTPResponse
FailResponse(reason string) HTTPResponse
}
type SpecialParamProvider interface {
SpecialParams(ctx context.Context, cmd SpecialParamCommand, cfg ComplexGameConfig) (map[string]any, error)
}
type H5PayVerifier interface {
VerifyH5Pay(ctx context.Context, req ComplexH5PayRequest, cfg ComplexGameConfig) error
}
每个 complex/*.php 对应一个 Go adapter,先迁移高流量渠道。渠道差异只允许存在 adapter 内,业务层接收统一后的 NormalizedComplexNotify。
| Go 模块 | 承接现有逻辑 | 迁移重点 |
|---|---|---|
protocol |
controller\Api、签名、AES、响应格式 |
兼容老 SDK |
account |
User、V1\User、实名相关控制器 |
token、实名、防沉迷 |
game |
Game、Role、Server、Version、OpenServer |
游戏、区服、角色缓存 |
payment |
Pay、PayNotify、GamePayService、PayService |
订单状态、幂等、金额 |
complex |
Complex、PayNotifyComplex、complex/* |
渠道适配器抽象 |
coupon |
Coupon、MemberCouponService |
领取、使用、过期 |
gift |
Gift、Welfare、Service |
礼包码、福利、客服 |
mlbb |
api/controller/mlbb/*、service/mlbb/* |
独立路由和验签 |
thirdparty |
Third, DataApi, YqlApi, DyApi |
外部数据接口隔离 |
SDKCodecMiddleware、AppAuthMiddleware、统一错误码。complex 渠道优先迁移。| 测试类型 | 重点 |
|---|---|
| Golden tests | AES、sign、auth_code、响应格式、历史字段兼容 |
| Unit tests | 账号规则、订单状态机、金额计算、渠道验签 |
| Repository tests | MySQL 查询、事务、唯一键、分页 |
| Integration tests | Redis 会话、支付 provider、实名 provider、CP 通知 |
| Contract tests | 每个 complex adapter 的登录与支付回调样本 |
| Shadow tests | 新旧接口响应对比,只记录不影响线上 |
支付和联运回调不建议直接双写。更稳妥的方式是先做回调样本重放和只读影子验证,确认后再灰度切流。
request_id、appid、user_id、game_id、order_no、channel、route。| 优先级 | 内容 | 原因 |
|---|---|---|
| P0 | 协议层、错误码、配置和日志 | 所有接口依赖 |
| P0 | 支付订单状态机和幂等模型 | 风险最高 |
| P1 | 登录、注册、会话、实名 | 核心用户链路 |
| P1 | 高流量支付渠道 | 直接影响收入 |
| P2 | 高流量 complex adapter | 联运差异大 |
| P2 | 游戏、礼包、优惠券、客服 | 业务完整性 |
| P3 | 低流量 Third/Data API | 可按需迁移 |
这个项目适合迁移到 Go,但不适合一次性重写。推荐采用“协议兼容 + 分域迁移 + 支付谨慎灰度”的方式推进。最关键的不是框架选择,而是把当前隐含在控制器、service、complex adapter 里的规则变成明确的接口、状态机、契约测试和可观测指标。