feat(server/pay): 首充钩子 — settle 内接邀请首充段发奖(first_paid_at 幂等)
This commit is contained in:
@@ -114,3 +114,23 @@ func (s *Service) OnRegister(ctx context.Context, inviteeID int64, inviteCode, d
|
||||
slog.Warn("reward: commit failed", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
// OnFirstPaidTx 在 pay webhook 的同一事务内调用:标记 first_paid_at,若确为首充且该用户
|
||||
// 是被邀请人(referral 命中且未发过首充奖)→ 发首充段双方各 PaidDays 天。幂等。
|
||||
func (s *Service) OnFirstPaidTx(ctx context.Context, tx *sql.Tx, inviteeID int64, now time.Time) error {
|
||||
first, err := s.st.MarkFirstPaidTx(ctx, tx, inviteeID, now)
|
||||
if err != nil || !first {
|
||||
return err // 非首充 → 不发
|
||||
}
|
||||
inviterID, status, ok, err := s.st.ReferralByInvitee(ctx, tx, inviteeID)
|
||||
if err != nil || !ok || status == "paid_rewarded" || status == "rejected" {
|
||||
return err // 无邀请关系 / 已发过 / 被拒 → 不发
|
||||
}
|
||||
if _, _, err := s.g.GrantRewardTx(ctx, tx, inviterID, s.cfg.PaidDays, "invite", "invite_paid_inviter", "ref-paid-inviter"); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, _, err := s.g.GrantRewardTx(ctx, tx, inviteeID, s.cfg.PaidDays, "invite", "invite_paid_invitee", "ref-paid-invitee"); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.st.MarkPaidRewardedTx(ctx, tx, inviteeID, now)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user