fix game zeeone expired session lookup
This commit is contained in:
parent
2a7fff405d
commit
2f3af25c0c
@ -1260,6 +1260,68 @@ func TestHandleZeeOneAccessTokenIgnoresStaleLaunchSessionGameID(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleZeeOneExpiredAccessTokenUsesScopedLaunchSession(t *testing.T) {
|
||||
secret := "zeeone-test-secret"
|
||||
userID := int64(328141720820654080)
|
||||
token := leaderccTestAccessToken(t, "lalu", userID, "1010", 1700000300)
|
||||
repo := &fakeRepository{
|
||||
platform: gamedomain.Platform{
|
||||
PlatformCode: "zeeone",
|
||||
AdapterType: gamedomain.AdapterZeeOneV1,
|
||||
CallbackSecretCiphertext: secret,
|
||||
AdapterConfigJSON: `{"merchant_id":307715,"platform_id":2032,"uid_mode":"display_user_id"}`,
|
||||
},
|
||||
sessions: []gamedomain.LaunchSession{
|
||||
{
|
||||
AppCode: "lalu",
|
||||
SessionID: "launch_session_1035",
|
||||
UserID: userID,
|
||||
DisplayUserID: "1010",
|
||||
PlatformCode: "zeeone",
|
||||
GameID: "zeeone_1035",
|
||||
ProviderGameID: "1035",
|
||||
LaunchTokenHash: stableHash(token),
|
||||
Status: gamedomain.SessionActive,
|
||||
ExpiresAtMS: 1700086800000,
|
||||
CreatedAtMS: 1700000000000,
|
||||
},
|
||||
{
|
||||
AppCode: "lalu",
|
||||
SessionID: "newer_wrong_game_session",
|
||||
UserID: userID,
|
||||
DisplayUserID: "1010",
|
||||
PlatformCode: "zeeone",
|
||||
GameID: "zeeone_1021",
|
||||
ProviderGameID: "1021",
|
||||
LaunchTokenHash: stableHash(token),
|
||||
Status: gamedomain.SessionActive,
|
||||
ExpiresAtMS: 1700086800000,
|
||||
CreatedAtMS: 1700000100000,
|
||||
},
|
||||
},
|
||||
}
|
||||
wallet := &fakeWallet{balanceAfter: 777}
|
||||
svc := New(Config{}, repo, wallet, &fakeUser{})
|
||||
svc.now = func() time.Time { return time.UnixMilli(1700000400000) }
|
||||
|
||||
changeBody := `{"appId":"M307715_P2032","userId":"1010","sessionId":"` + token + `","currency_diff":-50000,"diff_msg":"bet","game_id":1035,"room_id":"3255","change_time_at":1700000400,"order_id":"zee_order_expired_token_scoped"}`
|
||||
raw, _, err := svc.HandleCallback(context.Background(), &gamev1.CallbackRequest{
|
||||
Meta: &gamev1.RequestMeta{RequestId: "req-zeeone-expired-scoped", AppCode: "lalu"},
|
||||
PlatformCode: "zeeone",
|
||||
Operation: "change_balance",
|
||||
RawBody: zeeoneTestEnvelope(t, secret, changeBody, 1700000400000),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("HandleCallback change failed: %v", err)
|
||||
}
|
||||
if !strings.Contains(string(raw), `"code":0`) || strings.Contains(string(raw), "sessionId invalid") {
|
||||
t.Fatalf("zeeone expired JWT must fall back to scoped launch session: %s", raw)
|
||||
}
|
||||
if wallet.lastApply.GetUserId() != userID || wallet.lastApply.GetGameId() != "zeeone_1035" || wallet.lastApply.GetCoinAmount() != 50000 {
|
||||
t.Fatalf("zeeone scoped launch session must drive wallet command, got %+v", wallet.lastApply)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleZeeOneAllowsDebitAndCreditWithSameProviderOrderID(t *testing.T) {
|
||||
secret := "zeeone-test-secret"
|
||||
token := leaderccTestAccessToken(t, "lalu", 123456, "123456", 1700003600)
|
||||
|
||||
@ -143,7 +143,7 @@ func (s *Service) handleZeeOneOperation(ctx context.Context, app string, platfor
|
||||
case "change_balance", "change_coin", "update_coin":
|
||||
return s.handleZeeOneChangeBalance(ctx, app, config, req, body, requestHash)
|
||||
case "update_session", "refresh_session":
|
||||
return s.handleZeeOneUpdateSession(ctx, app, config, body)
|
||||
return s.handleZeeOneUpdateSession(ctx, app, req.GetPlatformCode(), config, body)
|
||||
case "repair_order", "repair":
|
||||
return s.handleZeeOneRepairOrder(ctx, app, platform, body)
|
||||
default:
|
||||
@ -232,7 +232,7 @@ func validateZeeOneAppID(config zeeoneAdapterConfig, appID string) error {
|
||||
}
|
||||
|
||||
func (s *Service) handleZeeOneUserInfo(ctx context.Context, app string, config zeeoneAdapterConfig, req *gamev1.CallbackRequest, body zeeoneBusinessBody) ([]byte, string, string, bool, string, error) {
|
||||
session, err := s.validZeeOneSession(ctx, app, body.SessionID)
|
||||
session, err := s.validZeeOneSession(ctx, app, req.GetPlatformCode(), body.SessionID, body.GameID)
|
||||
if err != nil {
|
||||
return zeeoneAdapterError(zeeoneCodeFromError(err), zeeoneMessageFromError(err), true, "")
|
||||
}
|
||||
@ -262,7 +262,7 @@ func (s *Service) handleZeeOneChangeBalance(ctx context.Context, app string, con
|
||||
if body.OrderID == "" || body.UserID == "" || body.SessionID == "" || body.GameID <= 0 || body.DiffMsg == "" {
|
||||
return zeeoneAdapterError(zeeoneCodeInvalidArgument, "invalid argument", true, body.OrderID)
|
||||
}
|
||||
session, err := s.validZeeOneSession(ctx, app, body.SessionID)
|
||||
session, err := s.validZeeOneSession(ctx, app, req.GetPlatformCode(), body.SessionID, body.GameID)
|
||||
if err != nil {
|
||||
return zeeoneAdapterError(zeeoneCodeFromError(err), zeeoneMessageFromError(err), true, body.OrderID)
|
||||
}
|
||||
@ -288,8 +288,8 @@ func (s *Service) handleZeeOneChangeBalance(ctx context.Context, app string, con
|
||||
return raw, contentType, strconv.Itoa(zeeoneCodeOK), true, body.OrderID, nil
|
||||
}
|
||||
|
||||
func (s *Service) handleZeeOneUpdateSession(ctx context.Context, app string, config zeeoneAdapterConfig, body zeeoneBusinessBody) ([]byte, string, string, bool, string, error) {
|
||||
session, err := s.validZeeOneSession(ctx, app, body.SessionID)
|
||||
func (s *Service) handleZeeOneUpdateSession(ctx context.Context, app string, platformCode string, config zeeoneAdapterConfig, body zeeoneBusinessBody) ([]byte, string, string, bool, string, error) {
|
||||
session, err := s.validZeeOneSession(ctx, app, platformCode, body.SessionID, body.GameID)
|
||||
if err != nil {
|
||||
return zeeoneAdapterError(zeeoneCodeFromError(err), zeeoneMessageFromError(err), true, "")
|
||||
}
|
||||
@ -321,7 +321,7 @@ func (s *Service) handleZeeOneRepairOrder(ctx context.Context, app string, platf
|
||||
return raw, contentType, strconv.Itoa(zeeoneCodeOK), true, body.OrderID, nil
|
||||
}
|
||||
|
||||
func (s *Service) validZeeOneSession(ctx context.Context, app string, sessionID string) (gamedomain.LaunchSession, error) {
|
||||
func (s *Service) validZeeOneSession(ctx context.Context, app string, platformCode string, sessionID string, gameID int64) (gamedomain.LaunchSession, error) {
|
||||
sessionID = strings.TrimSpace(sessionID)
|
||||
if sessionID == "" {
|
||||
return gamedomain.LaunchSession{}, xerr.New(xerr.Unauthorized, "sessionId not found")
|
||||
@ -333,7 +333,13 @@ func (s *Service) validZeeOneSession(ctx context.Context, app string, sessionID
|
||||
return session, nil
|
||||
}
|
||||
}
|
||||
if session, err := s.validYomiSession(ctx, app, sessionID); err == nil {
|
||||
providerGameID := ""
|
||||
if gameID > 0 {
|
||||
providerGameID = strconv.FormatInt(gameID, 10)
|
||||
}
|
||||
// App access token 过期后仍可能处于三方游戏局中;启动链路已经把同一 token 的厂商、游戏和 24h TTL
|
||||
// 落到 game_launch_sessions。这里必须按平台和游戏收窄,避免同一 access token 打开多款 ZeeOne 游戏时拿到旧会话。
|
||||
if session, err := s.validScopedYomiSession(ctx, app, platformCode, sessionID, providerGameID); err == nil {
|
||||
return session, nil
|
||||
}
|
||||
if strings.Count(sessionID, ".") == 2 {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user