Skip to content

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

  1. Player clicks a vote link on the SilkPanel frontend
  2. The URL contains their JID (game account ID) as a placeholder: https://toplist.com/vote?id={JID}
  3. Player completes the vote on the external toplist
  4. The toplist sends an HTTP POST callback (postback) to SilkPanel's postback URL
  5. SilkPanel verifies the callback (IP whitelist, webhook secret)
  6. SilkPanel identifies the player from the callback parameters
  7. Silk reward is granted to the player's game account
  8. A VotingLog record is created for tracking

Pre-Configured Voting Sites

The package comes with seeders for these toplists (all inactive by default):

SiteDefault RewardCooldown
Vote4Rewards2 Silk6 hours
XtremeTop1005 Silk12 hours
GTop1005 Silk12 hours
TopG5 Silk12 hours
Top100 Arena5 Silk12 hours
Arena Top1005 Silk12 hours
Silkroad Servers5 Silk12 hours
Private Servers5 Silk12 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

bash
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:

  1. Set is_active to true
  2. Configure reward amount and reward_silk_type
  3. Set appropriate timeout_hours (cooldown between votes)
  4. Set allowed_ips — get these from the toplist's documentation
  5. Set webhook_secret if the toplist supports it
  6. Copy the Postback URL shown in the admin panel
  7. 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:

  1. Create an account on the toplist website
  2. Add your server listing
  3. Find the postback/callback settings
  4. Enter SilkPanel's postback URL (from step 2.6)
  5. Note the allowed IPs the toplist uses for callbacks

Toplist-Specific Configuration

For each toplist, you need to know four things:

SettingWhere to Find
Postback URL formatThe toplist's documentation or settings page
Allowed IPsThe toplist's documentation (IPs they send callbacks from)
Parameter nameHow the toplist sends the user ID (e.g., custom, incentive, userid)
Webhook secretThe 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:

FieldDescription
slugUnique identifier (e.g., vote4rewards)
nameDisplay name
urlVote URL with {JID} placeholder
imageOptional logo URL
routeUnique route key for the postback URL
allowed_ipsComma-separated IP whitelist for callback validation
webhook_secretOptional HMAC secret for signature verification
rewardSilk amount per vote (default: 5)
reward_silk_typeType of silk to grant (default: silk_own)
timeout_hoursCooldown between votes per user (default: 12)
is_activeEnable/disable the site
sort_orderDisplay ordering

VotingLog

Individual vote records:

FieldDescription
voting_site_idLink to VotingSite
user_idLink to User
callback_receivedWhether the postback was received
reward_grantedWhether silk was granted
reward_amountAmount of silk granted
status_messageDetailed status/error message
ip_addressPlayer's vote IP
callback_ipToplist's postback IP
voted_atWhen the player voted
callback_atWhen the postback was received

Postback Controller Logic

When a postback is received, SilkPanel processes it in this order:

  1. Resolve voting site by route key → 404 if not found
  2. Check site is active403 if disabled
  3. Validate callback IP against allowed_ips403 if not whitelisted
  4. Verify webhook secret (HMAC if configured) → 403 if invalid
  5. 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) or User.name (string)
  6. Check vote cooldown (timeout_hours) → 429 if still in cooldown
  7. Create or update VotingLog
  8. Grant silk via SilkHelper::addSilk()
  9. 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

FeatureDescription
IP whitelistValidated per voting site against allowed_ips
HMAC verificationOptional webhook secret per site
Cooldown enforcementPrevents reward abuse (timeout_hours)
Idempotent processingDuplicate callbacks are safely handled
IP loggingBoth vote IP and callback IP are recorded
Payload storageFull 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_ips matches the toplist's callback IPs
  • Review Voting Logs in the admin panel — the status_message column contains detailed error info

403 errors in logs

  • IP not whitelisted — update allowed_ips for the voting site
  • Webhook secret mismatch — verify the secret matches on both sides

429 errors

  • User is still in cooldown — timeout_hours has 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 jid or name
  • 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.

Released under the PolyForm Shield License 1.0.0.