mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-30 23:14:37 +00:00
106 lines
2.9 KiB
Markdown
106 lines
2.9 KiB
Markdown
# Referral System
|
|
|
|
## Overview
|
|
|
|
Link-based referral system with one-time flat rewards for both parties.
|
|
|
|
- Reward: **$5** credit to referrer and **$5** credit to referred user
|
|
- Reward is one-time: awarded when the referred user's first subscription payment is confirmed
|
|
- No recurring rewards — once a referral is marked `CONVERTED`, subsequent payments return `already_converted`
|
|
|
|
## Main Rules
|
|
|
|
- Each user has one unique referral code with a shareable link.
|
|
- A user can claim a referral link only before their first subscription.
|
|
- Self-referral is blocked (user id + identity fields).
|
|
- Rewarding is idempotent:
|
|
- same payment cannot reward twice
|
|
- only one reward per referral (always one-time)
|
|
|
|
## Data Model
|
|
|
|
### `ReferralCode` (`referralcodes`)
|
|
|
|
- `userId` (unique)
|
|
- `referralCode` (unique)
|
|
|
|
### `Referral` (`referrals`)
|
|
|
|
- `referrerId`
|
|
- `referredUserId` (unique)
|
|
- `referralCode`
|
|
- `status`: `pending | converted`
|
|
- `sourceIp`, `deviceFingerprint`, `convertedAt`
|
|
|
|
### `ReferralTransaction` (`referraltransactions`)
|
|
|
|
- `referralId`, `referrerId`, `referredUserId`
|
|
- `sourcePaymentId`, `sourcePaymentGateway`, `sourcePaymentObjectId`
|
|
- `paymentAmountUsd`, `rewardAmountUsd`, `rewardRate` (Decimal128)
|
|
- `creditTransactionId`
|
|
- `recipientType`: `REFERRER | REFERRED`
|
|
- `idempotencyKey` (unique)
|
|
|
|
## Migration
|
|
|
|
Migration file: `src/migrations/1744200000000-referral-system.ts`
|
|
|
|
What it does:
|
|
|
|
- creates indexes for referral collections
|
|
- backfills missing referral codes for existing users
|
|
- backfills `Referral` records from legacy `user.referral.invitedBy`
|
|
- supports `users` and `tgusers` collections
|
|
|
|
### Run migration (non-interactive)
|
|
|
|
```bash
|
|
npx ts-migrate-mongoose up -f src/migrate.ts -a true
|
|
```
|
|
|
|
### Check migration status
|
|
|
|
```bash
|
|
npm run migrate:list
|
|
```
|
|
|
|
### Roll back referral migration (if needed)
|
|
|
|
```bash
|
|
npm run migrate:down
|
|
```
|
|
|
|
## Core Services
|
|
|
|
- `src/services/referral/referralCodeService.ts`
|
|
- ensures and fetches user referral codes
|
|
- `src/services/referral/referralService.ts`
|
|
- claim referral link, enforce eligibility (subscription-based gating), return referral stats
|
|
- `src/services/referral/referralRewardService.ts`
|
|
- award flat $5 credit to both referrer and referred user, upsert audit transactions, mark referral converted
|
|
|
|
## API
|
|
|
|
- `GET /referral/stats`
|
|
- returns code, referral link, totals, and referral rows
|
|
- `POST /referral/claim`
|
|
- request: `{ "code": "ABCD1234", "deviceFingerprint": "optional" }`
|
|
- supports `x-device-fingerprint` header
|
|
- only users who have never subscribed are eligible
|
|
|
|
## Payment Integration
|
|
|
|
Reward processing is triggered on successful payment flows in:
|
|
|
|
- `src/controllers/payment/coinbase/webhook.ts`
|
|
- `src/controllers/payment/stripe/handleWebhook.ts`
|
|
|
|
## Tests
|
|
|
|
Key test: `src/services/referral/__tests__/referralRewardService.test.ts`
|
|
|
|
- flat $5 reward to both parties
|
|
- conversion blocking (already_converted)
|
|
- payment idempotency
|
|
- partial-retry recovery
|