287 lines
8.9 KiB
Go
287 lines
8.9 KiB
Go
package firstrechargereward
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"chatapp3-golang/internal/config"
|
|
"chatapp3-golang/internal/integration"
|
|
"chatapp3-golang/internal/model"
|
|
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func TestSaveConfigReturnsRewardItems(t *testing.T) {
|
|
service, gateway, _ := newTestService(t)
|
|
gateway.groups[1001] = testRewardGroup(1001, "首冲礼包")
|
|
|
|
req := mustDecodeSaveConfigRequest(t, `{
|
|
"sysOrigin": "LIKEI",
|
|
"enabled": true,
|
|
"levelConfigs": [
|
|
{"level": 1, "rechargeAmount": "9.99", "rewardGroupId": "1001", "rewardGroupName": "首冲礼包", "enabled": true}
|
|
]
|
|
}`)
|
|
resp, err := service.SaveConfig(context.Background(), req)
|
|
if err != nil {
|
|
t.Fatalf("SaveConfig() error = %v", err)
|
|
}
|
|
if !resp.Configured || !resp.Enabled {
|
|
t.Fatalf("SaveConfig() configured/enabled = %v/%v", resp.Configured, resp.Enabled)
|
|
}
|
|
if len(resp.LevelConfigs) != 1 {
|
|
t.Fatalf("level count = %d", len(resp.LevelConfigs))
|
|
}
|
|
level := resp.LevelConfigs[0]
|
|
if level.RechargeAmountCents != 999 || level.RewardGroupID != 1001 {
|
|
t.Fatalf("level payload = %+v", level)
|
|
}
|
|
if len(level.RewardItems) != 1 || level.RewardItems[0].Name != "首冲礼包奖励" {
|
|
t.Fatalf("reward items = %+v", level.RewardItems)
|
|
}
|
|
}
|
|
|
|
func TestProcessRechargeEventFiltersAndGrantsOnce(t *testing.T) {
|
|
service, gateway, db := newTestService(t)
|
|
gateway.groups[1001] = testRewardGroup(1001, "首冲礼包")
|
|
gateway.profiles[123] = integration.UserProfile{
|
|
ID: integration.Int64Value(123),
|
|
Account: "100123",
|
|
UserNickname: "tester",
|
|
CountryCode: "SA",
|
|
}
|
|
|
|
_, err := service.SaveConfig(context.Background(), mustDecodeSaveConfigRequest(t, `{
|
|
"sysOrigin": "LIKEI",
|
|
"enabled": true,
|
|
"levelConfigs": [
|
|
{"level": 1, "rechargeAmount": "5.00", "rewardGroupId": "1001", "rewardGroupName": "首冲礼包", "enabled": true}
|
|
]
|
|
}`))
|
|
if err != nil {
|
|
t.Fatalf("SaveConfig() error = %v", err)
|
|
}
|
|
|
|
unsupported, err := service.ProcessRechargeEvent(context.Background(), mustDecodeRechargeEvent(t, `{
|
|
"eventId": "RECHARGE_SUCCESS:APPLE:1",
|
|
"sysOrigin": "LIKEI",
|
|
"userId": "123",
|
|
"amountCents": "999",
|
|
"payPlatform": "APPLE",
|
|
"paymentMethod": "APPLE",
|
|
"sourceOrderId": "1"
|
|
}`))
|
|
if err != nil {
|
|
t.Fatalf("unsupported ProcessRechargeEvent() error = %v", err)
|
|
}
|
|
if unsupported.Processed || unsupported.Reason != "unsupported_payment_method" {
|
|
t.Fatalf("unsupported response = %+v", unsupported)
|
|
}
|
|
|
|
lowAmount, err := service.ProcessRechargeEvent(context.Background(), mustDecodeRechargeEvent(t, `{
|
|
"eventId": "RECHARGE_SUCCESS:GOOGLE:LOW",
|
|
"sysOrigin": "LIKEI",
|
|
"userId": "123",
|
|
"amountCents": "499",
|
|
"payPlatform": "GOOGLE",
|
|
"paymentMethod": "GOOGLE",
|
|
"sourceOrderId": "LOW"
|
|
}`))
|
|
if err != nil {
|
|
t.Fatalf("low amount ProcessRechargeEvent() error = %v", err)
|
|
}
|
|
if lowAmount.Processed || lowAmount.Reason != "amount_not_reached" {
|
|
t.Fatalf("low amount response = %+v", lowAmount)
|
|
}
|
|
|
|
granted, err := service.ProcessRechargeEvent(context.Background(), mustDecodeRechargeEvent(t, `{
|
|
"eventId": "RECHARGE_SUCCESS:GOOGLE:OK",
|
|
"sysOrigin": "LIKEI",
|
|
"userId": "123",
|
|
"amountCents": "999",
|
|
"payPlatform": "GOOGLE",
|
|
"paymentMethod": "GOOGLE",
|
|
"sourceOrderId": "OK",
|
|
"occurredAt": "2026-05-21T12:00:00Z"
|
|
}`))
|
|
if err != nil {
|
|
t.Fatalf("grant ProcessRechargeEvent() error = %v", err)
|
|
}
|
|
if !granted.Processed || granted.Status != statusSuccess || granted.Level != 1 {
|
|
t.Fatalf("grant response = %+v", granted)
|
|
}
|
|
if len(gateway.rewardRequests) != 1 {
|
|
t.Fatalf("reward request count = %d", len(gateway.rewardRequests))
|
|
}
|
|
if got := gateway.rewardRequests[0].Origin; got != firstRechargeRewardOrigin {
|
|
t.Fatalf("reward origin = %s", got)
|
|
}
|
|
if len(gateway.notices) != 1 || gateway.notices[0].NoticeType != firstRechargeRewardNoticeType {
|
|
t.Fatalf("notices = %+v", gateway.notices)
|
|
}
|
|
|
|
duplicate, err := service.ProcessRechargeEvent(context.Background(), mustDecodeRechargeEvent(t, `{
|
|
"eventId": "RECHARGE_SUCCESS:GOOGLE:OK",
|
|
"sysOrigin": "LIKEI",
|
|
"userId": "123",
|
|
"amountCents": "999",
|
|
"payPlatform": "GOOGLE",
|
|
"paymentMethod": "GOOGLE",
|
|
"sourceOrderId": "OK"
|
|
}`))
|
|
if err != nil {
|
|
t.Fatalf("duplicate ProcessRechargeEvent() error = %v", err)
|
|
}
|
|
if !duplicate.Processed || duplicate.Status != statusSuccess {
|
|
t.Fatalf("duplicate response = %+v", duplicate)
|
|
}
|
|
if len(gateway.rewardRequests) != 1 {
|
|
t.Fatalf("duplicate reward request count = %d", len(gateway.rewardRequests))
|
|
}
|
|
|
|
thirdPartyUnknownPlatform, err := service.ProcessRechargeEvent(context.Background(), mustDecodeRechargeEvent(t, `{
|
|
"eventId": "RECHARGE_SUCCESS:THIRD_PARTY:CUSTOM",
|
|
"sysOrigin": "LIKEI",
|
|
"userId": "456",
|
|
"amountCents": "999",
|
|
"payPlatform": "CUSTOM_PAY",
|
|
"paymentMethod": "THIRD_PARTY",
|
|
"sourceOrderId": "CUSTOM"
|
|
}`))
|
|
if err != nil {
|
|
t.Fatalf("third party ProcessRechargeEvent() error = %v", err)
|
|
}
|
|
if !thirdPartyUnknownPlatform.Processed || thirdPartyUnknownPlatform.Status != statusSuccess {
|
|
t.Fatalf("third party response = %+v", thirdPartyUnknownPlatform)
|
|
}
|
|
if len(gateway.rewardRequests) != 2 {
|
|
t.Fatalf("third party reward request count = %d", len(gateway.rewardRequests))
|
|
}
|
|
|
|
googleDifferentPlatform, err := service.ProcessRechargeEvent(context.Background(), mustDecodeRechargeEvent(t, `{
|
|
"eventId": "RECHARGE_SUCCESS:GOOGLE:CUSTOM",
|
|
"sysOrigin": "LIKEI",
|
|
"userId": "789",
|
|
"amountCents": "999",
|
|
"payPlatform": "CUSTOM_GOOGLE_GATEWAY",
|
|
"paymentMethod": "GOOGLE",
|
|
"sourceOrderId": "CUSTOM_GOOGLE"
|
|
}`))
|
|
if err != nil {
|
|
t.Fatalf("google ProcessRechargeEvent() error = %v", err)
|
|
}
|
|
if !googleDifferentPlatform.Processed || googleDifferentPlatform.Status != statusSuccess {
|
|
t.Fatalf("google response = %+v", googleDifferentPlatform)
|
|
}
|
|
if len(gateway.rewardRequests) != 3 {
|
|
t.Fatalf("google reward request count = %d", len(gateway.rewardRequests))
|
|
}
|
|
|
|
var count int64
|
|
if err := db.Model(&model.FirstRechargeRewardGrantRecord{}).Count(&count).Error; err != nil {
|
|
t.Fatalf("count grant records: %v", err)
|
|
}
|
|
if count != 3 {
|
|
t.Fatalf("grant record count = %d", count)
|
|
}
|
|
}
|
|
|
|
func newTestService(t *testing.T) (*Service, *fakeGateway, *gorm.DB) {
|
|
t.Helper()
|
|
db, err := gorm.Open(sqlite.Open("file:"+t.Name()+"?mode=memory&cache=shared"), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatalf("open sqlite: %v", err)
|
|
}
|
|
if err := db.AutoMigrate(
|
|
&model.FirstRechargeRewardConfig{},
|
|
&model.FirstRechargeRewardLevel{},
|
|
&model.FirstRechargeRewardGrantRecord{},
|
|
); err != nil {
|
|
t.Fatalf("migrate sqlite: %v", err)
|
|
}
|
|
gateway := &fakeGateway{
|
|
groups: map[int64]integration.RewardGroupDetail{},
|
|
profiles: map[int64]integration.UserProfile{},
|
|
}
|
|
service := NewService(config.Config{
|
|
FirstRechargeReward: config.FirstRechargeRewardConfig{
|
|
DefaultSysOrigin: "LIKEI",
|
|
},
|
|
}, db, gateway)
|
|
return service, gateway, db
|
|
}
|
|
|
|
func mustDecodeSaveConfigRequest(t *testing.T, raw string) SaveConfigRequest {
|
|
t.Helper()
|
|
var req SaveConfigRequest
|
|
if err := json.Unmarshal([]byte(raw), &req); err != nil {
|
|
t.Fatalf("decode SaveConfigRequest: %v", err)
|
|
}
|
|
return req
|
|
}
|
|
|
|
func mustDecodeRechargeEvent(t *testing.T, raw string) RechargeEvent {
|
|
t.Helper()
|
|
var event RechargeEvent
|
|
if err := json.Unmarshal([]byte(raw), &event); err != nil {
|
|
t.Fatalf("decode RechargeEvent: %v", err)
|
|
}
|
|
return event
|
|
}
|
|
|
|
func testRewardGroup(id int64, name string) integration.RewardGroupDetail {
|
|
return integration.RewardGroupDetail{
|
|
ID: integration.Int64Value(id),
|
|
Name: name,
|
|
RewardConfigList: []integration.RewardGroupItem{
|
|
{
|
|
ID: integration.Int64Value(11),
|
|
Type: "PROPS",
|
|
Name: name + "奖励",
|
|
Content: "10001",
|
|
Quantity: integration.Int64Value(1),
|
|
Cover: "https://example.com/reward.png",
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
type fakeGateway struct {
|
|
groups map[int64]integration.RewardGroupDetail
|
|
profiles map[int64]integration.UserProfile
|
|
rewardRequests []integration.SendActivityRewardRequest
|
|
notices []integration.OfficialNoticeCustomizeRequest
|
|
cacheRemoved []int64
|
|
}
|
|
|
|
func (g *fakeGateway) GetRewardGroupDetail(_ context.Context, groupID int64) (integration.RewardGroupDetail, error) {
|
|
if group, ok := g.groups[groupID]; ok {
|
|
return group, nil
|
|
}
|
|
return testRewardGroup(groupID, "默认奖励组"), nil
|
|
}
|
|
|
|
func (g *fakeGateway) GetUserProfile(_ context.Context, userID int64) (integration.UserProfile, error) {
|
|
if profile, ok := g.profiles[userID]; ok {
|
|
return profile, nil
|
|
}
|
|
return integration.UserProfile{ID: integration.Int64Value(userID)}, nil
|
|
}
|
|
|
|
func (g *fakeGateway) SendActivityReward(_ context.Context, req integration.SendActivityRewardRequest) error {
|
|
g.rewardRequests = append(g.rewardRequests, req)
|
|
return nil
|
|
}
|
|
|
|
func (g *fakeGateway) SendOfficialNoticeCustomize(_ context.Context, req integration.OfficialNoticeCustomizeRequest) error {
|
|
g.notices = append(g.notices, req)
|
|
return nil
|
|
}
|
|
|
|
func (g *fakeGateway) RemoveUserProfileCacheAll(_ context.Context, userID int64) error {
|
|
g.cacheRemoved = append(g.cacheRemoved, userID)
|
|
return nil
|
|
}
|