diff --git a/internal/service/gameopen/service.go b/internal/service/gameopen/service.go index 67fb383..f75bc82 100644 --- a/internal/service/gameopen/service.go +++ b/internal/service/gameopen/service.go @@ -101,23 +101,26 @@ func (s *GameOpenService) HandleUpdateCoin(ctx context.Context, req UpdateCoinRe s.saveCallbackLog(ctx, "update-coin", rawJSON, resp, credential.SysOrigin, req, &userID, gameOpenLogStatusFailed) return resp } - if !exists { - if err := s.java.ChangeGoldBalance(ctx, integration.GoldReceiptCommand{ - ReceiptType: receiptTypeFromType(req.Type), - UserID: userID, - SysOrigin: credential.SysOrigin, - EventID: eventID, - Remark: fmt.Sprintf("game=%s rewardType=%d round=%s", req.GameID, req.RewardType, req.RoundID), - Amount: integration.NewPennyAmountPayloadFromDollar(req.Coin), - CloseDelayAsset: false, - OpUserType: "APP", - CustomizeOrigin: "GAME_OPEN_" + strings.TrimSpace(req.GameID), - CustomizeOriginDesc: "GAME OPEN[" + strings.TrimSpace(req.GameID) + "]", - }); err != nil { - resp := failResponse(gameOpenCodeServerError, err.Error()) - s.saveCallbackLog(ctx, "update-coin", rawJSON, resp, credential.SysOrigin, req, &userID, gameOpenLogStatusFailed) - return resp - } + if exists { + resp := failResponse(gameOpenCodeDuplicateOrder, "duplicate orderId") + s.saveCallbackLog(ctx, "update-coin", rawJSON, resp, credential.SysOrigin, req, &userID, gameOpenLogStatusFailed) + return resp + } + if err := s.java.ChangeGoldBalance(ctx, integration.GoldReceiptCommand{ + ReceiptType: receiptTypeFromType(req.Type), + UserID: userID, + SysOrigin: credential.SysOrigin, + EventID: eventID, + Remark: fmt.Sprintf("game=%s rewardType=%d round=%s", req.GameID, req.RewardType, req.RoundID), + Amount: integration.NewPennyAmountPayloadFromDollar(req.Coin), + CloseDelayAsset: false, + OpUserType: "APP", + CustomizeOrigin: "GAME_OPEN_" + strings.TrimSpace(req.GameID), + CustomizeOriginDesc: "GAME OPEN[" + strings.TrimSpace(req.GameID) + "]", + }); err != nil { + resp := failResponse(gameOpenCodeServerError, err.Error()) + s.saveCallbackLog(ctx, "update-coin", rawJSON, resp, credential.SysOrigin, req, &userID, gameOpenLogStatusFailed) + return resp } balance, err := s.readUserBalance(ctx, userID) diff --git a/internal/service/gameopen/service_test.go b/internal/service/gameopen/service_test.go index 7f8d55b..e615d12 100644 --- a/internal/service/gameopen/service_test.go +++ b/internal/service/gameopen/service_test.go @@ -141,6 +141,45 @@ func TestHandleUpdateCoin(t *testing.T) { } } +func TestHandleUpdateCoinDuplicateOrderReturns10003(t *testing.T) { + gateway := &stubGateway{ + credential: integration.UserCredential{UserID: 1234567, SysOrigin: "LIKEI"}, + profile: integration.UserProfile{ + ID: 1234567, + Account: "1234567", + }, + balance: 99, + exists: true, + } + service := NewGameOpenService(config.Config{ + GameOpen: config.GameOpenConfig{AppKey: "game-open-test-key"}, + }, nil, gateway) + req := UpdateCoinRequest{ + OrderID: "27822d8ba4a34d0e8db3e049716d427d", + GameID: "101", + RoundID: "round-1", + UID: "1234567", + Coin: 15, + Type: 2, + RewardType: 2, + Token: "token", + WinID: "win-1", + RoomID: "room-1", + } + req.Sign = buildUpdateCoinSign(req, "game-open-test-key") + + resp := service.HandleUpdateCoin(context.Background(), req, "{}") + if resp.ErrorCode != gameOpenCodeDuplicateOrder { + t.Fatalf("HandleUpdateCoin() errorCode = %d, want %d", resp.ErrorCode, gameOpenCodeDuplicateOrder) + } + if resp.ErrorMsg != "duplicate orderId" { + t.Fatalf("HandleUpdateCoin() errorMsg = %q", resp.ErrorMsg) + } + if gateway.cmd.EventID != "" { + t.Fatalf("HandleUpdateCoin() should not change balance for duplicate order, got event id %q", gateway.cmd.EventID) + } +} + func TestHandleQueryUserAcceptsAccountUID(t *testing.T) { gateway := &stubGateway{ credential: integration.UserCredential{UserID: 4569421795454615552, SysOrigin: "LIKEI"}, diff --git a/internal/service/gameopen/types.go b/internal/service/gameopen/types.go index 7ecb361..7c55910 100644 --- a/internal/service/gameopen/types.go +++ b/internal/service/gameopen/types.go @@ -11,6 +11,7 @@ import ( const ( gameOpenCodeSuccess = 0 + gameOpenCodeDuplicateOrder = 10003 gameOpenCodeBadRequest = 4001 gameOpenCodeSignatureError = 4002 gameOpenCodeTokenInvalid = 4003