Allow zero coin game outbox events
This commit is contained in:
parent
d2dbc88e5f
commit
1b8241c3d2
@ -40,18 +40,8 @@ type GameOutboxMessage struct {
|
||||
// EncodeGameOutboxMessage serializes a game fact for fanout through RocketMQ.
|
||||
func EncodeGameOutboxMessage(message GameOutboxMessage) ([]byte, error) {
|
||||
message.MessageType = MessageTypeGameOutboxEvent
|
||||
if strings.TrimSpace(message.AppCode) == "" ||
|
||||
strings.TrimSpace(message.EventID) == "" ||
|
||||
strings.TrimSpace(message.EventType) == "" ||
|
||||
strings.TrimSpace(message.GameID) == "" ||
|
||||
message.OccurredAtMS <= 0 {
|
||||
return nil, errors.New("game outbox message is incomplete")
|
||||
}
|
||||
if message.EventType == EventTypeGameOrderSettled && (strings.TrimSpace(message.OrderID) == "" ||
|
||||
message.UserID <= 0 ||
|
||||
strings.TrimSpace(message.OpType) == "" ||
|
||||
message.CoinAmount <= 0) {
|
||||
return nil, errors.New("game order outbox message is incomplete")
|
||||
if err := validateGameOutboxMessage(message); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if strings.TrimSpace(message.PayloadJSON) == "" {
|
||||
message.PayloadJSON = "{}"
|
||||
@ -68,21 +58,30 @@ func DecodeGameOutboxMessage(body []byte) (GameOutboxMessage, error) {
|
||||
if message.MessageType != MessageTypeGameOutboxEvent {
|
||||
return GameOutboxMessage{}, errors.New("unexpected game outbox message_type")
|
||||
}
|
||||
if strings.TrimSpace(message.AppCode) == "" ||
|
||||
strings.TrimSpace(message.EventID) == "" ||
|
||||
strings.TrimSpace(message.EventType) == "" ||
|
||||
strings.TrimSpace(message.GameID) == "" ||
|
||||
message.OccurredAtMS <= 0 {
|
||||
return GameOutboxMessage{}, errors.New("game outbox message is incomplete")
|
||||
}
|
||||
if message.EventType == EventTypeGameOrderSettled && (strings.TrimSpace(message.OrderID) == "" ||
|
||||
message.UserID <= 0 ||
|
||||
strings.TrimSpace(message.OpType) == "" ||
|
||||
message.CoinAmount <= 0) {
|
||||
return GameOutboxMessage{}, errors.New("game order outbox message is incomplete")
|
||||
if err := validateGameOutboxMessage(message); err != nil {
|
||||
return GameOutboxMessage{}, err
|
||||
}
|
||||
if strings.TrimSpace(message.PayloadJSON) == "" {
|
||||
message.PayloadJSON = "{}"
|
||||
}
|
||||
return message, nil
|
||||
}
|
||||
|
||||
func validateGameOutboxMessage(message GameOutboxMessage) error {
|
||||
if strings.TrimSpace(message.AppCode) == "" ||
|
||||
strings.TrimSpace(message.EventID) == "" ||
|
||||
strings.TrimSpace(message.EventType) == "" ||
|
||||
strings.TrimSpace(message.GameID) == "" ||
|
||||
message.OccurredAtMS <= 0 {
|
||||
return errors.New("game outbox message is incomplete")
|
||||
}
|
||||
if message.EventType == EventTypeGameOrderSettled && (strings.TrimSpace(message.OrderID) == "" ||
|
||||
message.UserID <= 0 ||
|
||||
strings.TrimSpace(message.OpType) == "" ||
|
||||
message.CoinAmount < 0) {
|
||||
// 厂商可能发送 0 金额派奖或 0 金额结算确认;这类订单是已落库事实,必须允许 MQ 投递。
|
||||
// 负数仍然不是合法订单金额,扣减方向必须由 op_type=debit 表达,不能把符号塞进金额字段。
|
||||
return errors.New("game order outbox message is incomplete")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
67
pkg/gamemq/messages_test.go
Normal file
67
pkg/gamemq/messages_test.go
Normal file
@ -0,0 +1,67 @@
|
||||
package gamemq
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEncodeGameOutboxMessageAllowsZeroCoinGameOrder(t *testing.T) {
|
||||
message := GameOutboxMessage{
|
||||
AppCode: "lalu",
|
||||
EventID: "GameOrderSettled:gord_zero_credit",
|
||||
EventType: EventTypeGameOrderSettled,
|
||||
OrderID: "gord_zero_credit",
|
||||
UserID: 42,
|
||||
PlatformCode: "zeeone",
|
||||
GameID: "1021",
|
||||
OpType: "credit",
|
||||
CoinAmount: 0,
|
||||
OccurredAtMS: 1781199149295,
|
||||
}
|
||||
|
||||
body, err := EncodeGameOutboxMessage(message)
|
||||
if err != nil {
|
||||
t.Fatalf("zero coin game order should be publishable: %v", err)
|
||||
}
|
||||
decoded, err := DecodeGameOutboxMessage(body)
|
||||
if err != nil {
|
||||
t.Fatalf("zero coin game order should be decodable: %v", err)
|
||||
}
|
||||
if decoded.CoinAmount != 0 || decoded.PayloadJSON != "{}" {
|
||||
t.Fatalf("decoded zero coin order mismatch: %+v", decoded)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeGameOutboxMessageRejectsNegativeGameOrderAmount(t *testing.T) {
|
||||
_, err := EncodeGameOutboxMessage(GameOutboxMessage{
|
||||
AppCode: "lalu",
|
||||
EventID: "GameOrderSettled:gord_negative",
|
||||
EventType: EventTypeGameOrderSettled,
|
||||
OrderID: "gord_negative",
|
||||
UserID: 42,
|
||||
PlatformCode: "zeeone",
|
||||
GameID: "1021",
|
||||
OpType: "credit",
|
||||
CoinAmount: -1,
|
||||
OccurredAtMS: 1781199149295,
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatalf("negative game order amount should be rejected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeGameOutboxMessageAllowsSelfGameEventWithoutOrderFields(t *testing.T) {
|
||||
body, err := EncodeGameOutboxMessage(GameOutboxMessage{
|
||||
AppCode: "lalu",
|
||||
EventID: "SelfGameMatchSettled:match_1",
|
||||
EventType: EventTypeSelfGameMatchSettled,
|
||||
UserID: 42,
|
||||
PlatformCode: "self",
|
||||
GameID: "dice",
|
||||
PayloadJSON: `{"match_id":"match_1"}`,
|
||||
OccurredAtMS: 1781199149295,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("self game fact should not require order fields: %v", err)
|
||||
}
|
||||
if _, err := DecodeGameOutboxMessage(body); err != nil {
|
||||
t.Fatalf("self game fact should decode: %v", err)
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user