feat(#4): 抽奖中奖用户文案调整

- 免费时长: 用户消息改为「稍后您的 N 天免费时长将会自动添加至您的账户。
  如果超过24小时未添加成功,请联系人工客服处理。」(N=中奖天数动态)
  ledger.payload.message 仍保留descriptive内部文案供后台对账
- 人工发放(crypto/manual): 消息改为「请凭此截图直接联系人工客服兑换奖励。」

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-17 02:56:38 -07:00
parent 2c1ee78bc4
commit 5ef3f2717e
4 changed files with 20 additions and 14 deletions
+3 -3
View File
@@ -422,12 +422,12 @@ func (s *Service) dispatchOrEnqueueClaim(ctx context.Context, tx *gorm.DB, req R
return lottery.DispatchResult{State: lottery.DispatchStateAutoClaimed, Message: "谢谢参与"}, pendingClaimInfo{}, nil
}
if s.deps.Registry == nil {
return lottery.DispatchResult{State: lottery.DispatchStatePendingClaim, Message: "等待人工发放"}, pendingClaimInfo{}, nil
return lottery.DispatchResult{State: lottery.DispatchStatePendingClaim, Message: "请凭此截图直接联系人工客服兑换奖励。"}, pendingClaimInfo{}, nil
}
prizeHandler, err := s.deps.Registry.MustGet(prize.Type)
if err != nil {
if errors.Is(err, lottery.ErrHandlerNotRegistered) {
return lottery.DispatchResult{State: lottery.DispatchStatePendingClaim, Message: "等待人工发放"}, pendingClaimInfo{}, nil
return lottery.DispatchResult{State: lottery.DispatchStatePendingClaim, Message: "请凭此截图直接联系人工客服兑换奖励。"}, pendingClaimInfo{}, nil
}
return lottery.DispatchResult{}, pendingClaimInfo{}, wrapInternal(err)
}
@@ -472,7 +472,7 @@ func (s *Service) dispatchOrEnqueueClaim(ctx context.Context, tx *gorm.DB, req R
}
return lottery.DispatchResult{
State: lottery.DispatchStatePendingClaim,
Message: "等待填写领奖信息",
Message: "请凭此截图直接联系人工客服兑换奖励。",
}, pendingClaimInfo{
ExpiresAt: expiresAt,
ClaimFormSchema: schema,
+2 -2
View File
@@ -1008,7 +1008,7 @@ func TestDraw_E2E_VPNDurationAutoCreatesSubscription(t *testing.T) {
if !res.Claim.AutoClaimed {
t.Fatalf("expected AutoClaimed=true, got %+v", res.Claim)
}
if res.Message != "已新建订阅并加 5 天" {
if !strings.Contains(res.Message, "免费时长将会自动添加") {
t.Fatalf("expected auto-create message, got %q", res.Message)
}
if res.Prize == nil || res.Prize.Type != lottery.PrizeTypeVPNDuration {
@@ -1072,7 +1072,7 @@ func TestDraw_E2E_VPNDurationNoPlanSkipsGrant(t *testing.T) {
if err != nil {
t.Fatalf("Draw: %v", err)
}
if !strings.Contains(res.Message, "跳过") {
if !strings.Contains(res.Message, "免费时长将会自动添加") {
t.Fatalf("expected skip message, got %q", res.Message)
}
if err := mock.ExpectationsWereMet(); err != nil {
+10 -4
View File
@@ -105,6 +105,12 @@ type vpnDurationPayload struct {
Message string `json:"message"`
}
// vpnDurationUserMessage 是免费时长中奖后返回给用户的提示文案(N=中奖天数,动态)。
// 内部对账用的详细结果仍写在 ledger.payload.message(如"已加 N 天到订阅")。
func vpnDurationUserMessage(days int) string {
return fmt.Sprintf("稍后您的 %d 天免费时长将会自动添加至您的账户。如果超过24小时未添加成功,请联系人工客服处理。", days)
}
// Dispatch 在 caller 的事务内发放订阅时长。
func (h *VPNDurationHandler) Dispatch(ctx context.Context, tx *gorm.DB, req lottery.DispatchRequest) (lottery.DispatchResult, error) {
if tx == nil {
@@ -151,7 +157,7 @@ func (h *VPNDurationHandler) Dispatch(ctx context.Context, tx *gorm.DB, req lott
if payload.Message == "" {
payload.Message = "已加到订阅"
}
return lottery.DispatchResult{State: lottery.DispatchStateAutoClaimed, Message: payload.Message}, nil
return lottery.DispatchResult{State: lottery.DispatchStateAutoClaimed, Message: vpnDurationUserMessage(cfg.DurationDays)}, nil
}
// 未存在 → 真实发放。查用户的活跃订阅。
@@ -174,7 +180,7 @@ func (h *VPNDurationHandler) Dispatch(ctx context.Context, tx *gorm.DB, req lott
if err := h.writeBackPayload(ctx, tx, row.Id, payload); err != nil {
return lottery.DispatchResult{}, err
}
return lottery.DispatchResult{State: lottery.DispatchStateAutoClaimed, Message: payload.Message}, nil
return lottery.DispatchResult{State: lottery.DispatchStateAutoClaimed, Message: vpnDurationUserMessage(cfg.DurationDays)}, nil
}
payload := vpnDurationPayload{
EffectiveUserID: effectiveUserID,
@@ -184,7 +190,7 @@ func (h *VPNDurationHandler) Dispatch(ctx context.Context, tx *gorm.DB, req lott
if err := h.writeBackPayload(ctx, tx, row.Id, payload); err != nil {
return lottery.DispatchResult{}, err
}
return lottery.DispatchResult{State: lottery.DispatchStateAutoClaimed, Message: payload.Message}, nil
return lottery.DispatchResult{State: lottery.DispatchStateAutoClaimed, Message: vpnDurationUserMessage(cfg.DurationDays)}, nil
}
if findErr != nil {
return lottery.DispatchResult{}, fmt.Errorf("find active subscribe for user %d: %w", effectiveUserID, findErr)
@@ -218,7 +224,7 @@ func (h *VPNDurationHandler) Dispatch(ctx context.Context, tx *gorm.DB, req lott
if err := h.writeBackPayload(ctx, tx, row.Id, payload); err != nil {
return lottery.DispatchResult{}, err
}
return lottery.DispatchResult{State: lottery.DispatchStateAutoClaimed, Message: payload.Message}, nil
return lottery.DispatchResult{State: lottery.DispatchStateAutoClaimed, Message: vpnDurationUserMessage(cfg.DurationDays)}, nil
}
// findActiveSubscribe 优先走 UserModel.FindActiveSubscribe;未找到则回退到
@@ -130,7 +130,7 @@ func TestVPNDuration_IdempotentHitReturnsStoredMessage(t *testing.T) {
if res.State != lottery.DispatchStateAutoClaimed {
t.Fatalf("expected auto_claimed, got %q", res.State)
}
if res.Message != "已加 3 天到订阅" {
if !strings.Contains(res.Message, "免费时长将会自动添加") {
t.Fatalf("expected stored message, got %q", res.Message)
}
}
@@ -176,7 +176,7 @@ func TestVPNDuration_NoActiveSubscribeSkipsWithoutError(t *testing.T) {
if res.State != lottery.DispatchStateAutoClaimed {
t.Fatalf("expected auto_claimed even on skip, got %q", res.State)
}
if !strings.Contains(res.Message, "跳过") {
if !strings.Contains(res.Message, "免费时长将会自动添加") {
t.Fatalf("expected skip message, got %q", res.Message)
}
}
@@ -234,7 +234,7 @@ func TestVPNDuration_ExtendsExistingExpireTime(t *testing.T) {
if !updateCalled {
t.Fatalf("expected UpdateSubscribe to be called")
}
if res.Message != "已加 3 天到订阅" {
if !strings.Contains(res.Message, "免费时长将会自动添加") {
t.Fatalf("unexpected message: %q", res.Message)
}
}
@@ -395,7 +395,7 @@ func TestVPNDuration_NoActiveSubscribeCreatesSubscription(t *testing.T) {
if res.State != lottery.DispatchStateAutoClaimed {
t.Fatalf("expected auto_claimed, got %q", res.State)
}
if res.Message != "已新建订阅并加 5 天" {
if !strings.Contains(res.Message, "免费时长将会自动添加") {
t.Fatalf("unexpected message: %q", res.Message)
}
}
@@ -439,7 +439,7 @@ func TestVPNDuration_NoActiveSubscribeNoPlanStillSkips(t *testing.T) {
if err != nil {
t.Fatalf("Dispatch: %v", err)
}
if !strings.Contains(res.Message, "跳过") {
if !strings.Contains(res.Message, "免费时长将会自动添加") {
t.Fatalf("expected skip message, got %q", res.Message)
}
}