Voting
SilkPanel CMS includes a voting system that integrates with popular Silkroad Online toplists. Players vote on external sites, the toplist sends a postback to SilkPanel, and the player automatically receives Silk as a reward.
How It Works
- Player clicks a vote link on the SilkPanel frontend
- The URL contains their JID (game account ID) as a placeholder:
https://toplist.com/vote?id={JID} - Player completes the vote on the external toplist
- The toplist sends an HTTP POST callback (postback) to SilkPanel's postback URL
- SilkPanel verifies the callback (IP whitelist, webhook secret)
- SilkPanel identifies the player from the callback parameters
- Silk reward is granted to the player's game account
- A
VotingLogrecord is created for tracking
Pre-Configured Voting Sites
The package comes with seeders for these toplists (all inactive by default):
| Site | Default Reward | Cooldown |
|---|---|---|
| Vote4Rewards | 2 Silk | 6 hours |
| XtremeTop100 | 5 Silk | 12 hours |
| GTop100 | 5 Silk | 12 hours |
| TopG | 5 Silk | 12 hours |
| Top100 Arena | 5 Silk | 12 hours |
| Arena Top100 | 5 Silk | 12 hours |
| Silkroad Servers | 5 Silk | 12 hours |
| Private Servers | 5 Silk | 12 hours |
TIP
All sites are inactive by default. Enable only the toplists you've registered with and configured postback URLs for.
Postback URL
Each voting site has a unique postback URL:
https://yourdomain.com/postback/{route-key}The {route-key} is a unique, per-site value shown in the admin panel. This URL must be configured in each toplist's postback/callback settings.
WARNING
The postback URL is different for each voting site. Always copy the exact URL from the admin panel — do not construct it manually.
Step-by-Step Setup
1. Publish Migrations & Seed
php artisan migrate
php artisan db:seed --class="SilkPanel\Voting\Database\Seeders\VotingSiteSeeder"2. Configure Voting Sites in Admin Panel
Go to Admin Panel → Voting → Voting Sites. For each site you want to enable:
- Set is_active to
true - Configure reward amount and reward_silk_type
- Set appropriate timeout_hours (cooldown between votes)
- Set allowed_ips — get these from the toplist's documentation
- Set webhook_secret if the toplist supports it
- Copy the Postback URL shown in the admin panel
- Paste it into the toplist's callback/postback configuration
3. Configure Vote URLs
The url field uses {JID} as a placeholder for the player's game account ID.
https://vote4rewards.de/vote/fc55129-014d-4d6b-aeba-68d83ff414bb?rewarder={JID}When a player clicks the vote link, {JID} is automatically replaced with their game account ID.
4. Register on Toplists
For each toplist you want to use:
- Create an account on the toplist website
- Add your server listing
- Find the postback/callback settings
- Enter SilkPanel's postback URL (from step 2.6)
- Note the allowed IPs the toplist uses for callbacks
Toplist-Specific Configuration
For each toplist, you need to know four things:
| Setting | Where to Find |
|---|---|
| Postback URL format | The toplist's documentation or settings page |
| Allowed IPs | The toplist's documentation (IPs they send callbacks from) |
| Parameter name | How the toplist sends the user ID (e.g., custom, incentive, userid) |
| Webhook secret | The toplist's settings page (if they support signed callbacks) |
TIP
The postback controller automatically tries multiple common parameter names (userid, user_id, uid, id, jid, custom, incentive, pingUsername, rewarder, voter_id, username), so most toplists work out of the box without any extra configuration.
Database Models
VotingSite
Configuration per toplist:
| Field | Description |
|---|---|
slug | Unique identifier (e.g., vote4rewards) |
name | Display name |
url | Vote URL with {JID} placeholder |
image | Optional logo URL |
route | Unique route key for the postback URL |
allowed_ips | Comma-separated IP whitelist for callback validation |
webhook_secret | Optional HMAC secret for signature verification |
reward | Silk amount per vote (default: 5) |
reward_silk_type | Type of silk to grant (default: silk_own) |
timeout_hours | Cooldown between votes per user (default: 12) |
is_active | Enable/disable the site |
sort_order | Display ordering |
VotingLog
Individual vote records:
| Field | Description |
|---|---|
voting_site_id | Link to VotingSite |
user_id | Link to User |
callback_received | Whether the postback was received |
reward_granted | Whether silk was granted |
reward_amount | Amount of silk granted |
status_message | Detailed status/error message |
ip_address | Player's vote IP |
callback_ip | Toplist's postback IP |
voted_at | When the player voted |
callback_at | When the postback was received |
Postback Controller Logic
When a postback is received, SilkPanel processes it in this order:
- Resolve voting site by route key →
404if not found - Check site is active →
403if disabled - Validate callback IP against
allowed_ips→403if not whitelisted - Verify webhook secret (HMAC if configured) →
403if invalid - Resolve user from callback parameters — tries these fields in order:
userid,user_id,uid,id,jid,custom,incentive,pingUsername,rewarder,voter_id,username- Matches against
User.jid(numeric) orUser.name(string)
- Matches against
- Check vote cooldown (
timeout_hours) →429if still in cooldown - Create or update VotingLog
- Grant silk via
SilkHelper::addSilk() - Return JSON response
Admin Panel (Filament)
Under the Voting navigation group:
Voting Sites
- List all sites with active toggle, reward amount, timeout, vote count
- Edit: general settings, reward config, postback/callback settings
- Shows the full Postback URL (read-only) for easy copy-paste
- Allowed IPs as a tag input
- Cannot create new sites (seeded only), can edit existing ones
Voting Logs
- Read-only log of all vote records
- Columns: User, Site, Callback status, Reward status, Amount, Status Message, IPs, Timestamps
- Filterable by: Voting Site, Callback Status (Received/Pending), Reward Status (Granted/Not Granted)
- View detail page with full callback payload
Silk Distribution
Same mechanism as the donation system:
- Uses
SilkHelper::addSilk($jid, $amount, $silk_type) - Handles VSRO and ISRO server versions
- Silk type is configurable per voting site (
silk_own,silk_gift,silk_point)
Security
| Feature | Description |
|---|---|
| IP whitelist | Validated per voting site against allowed_ips |
| HMAC verification | Optional webhook secret per site |
| Cooldown enforcement | Prevents reward abuse (timeout_hours) |
| Idempotent processing | Duplicate callbacks are safely handled |
| IP logging | Both vote IP and callback IP are recorded |
| Payload storage | Full callback payload stored for debugging |
WARNING
Always configure allowed_ips for each voting site. Without IP whitelisting, anyone could forge a postback request and grant themselves silk.
Troubleshooting
No reward granted
- Check
allowed_ipsmatches the toplist's callback IPs - Review Voting Logs in the admin panel — the
status_messagecolumn contains detailed error info
403 errors in logs
- IP not whitelisted — update
allowed_ipsfor the voting site - Webhook secret mismatch — verify the secret matches on both sides
429 errors
- User is still in cooldown —
timeout_hourshas not elapsed since their last vote - This is expected behavior to prevent abuse
404 errors
- Wrong postback route key configured in the toplist
- Copy the exact URL from the admin panel
User not found
- The parameter the toplist sends doesn't match any user's
jidorname - Check what parameter name the toplist uses and verify the player has a linked game account
TIP
The Voting Logs page in the admin panel is your best debugging tool. Every postback is logged with its full payload, IP addresses, and a detailed status message explaining exactly what happened.