Campuscard - 北大校园卡 CLI
A CLI client for PKU's campus card system (Synjones platform at bdcard.pku.edu.cn).
Architecture
- Crate location:
crates/campuscard/ - Auth flow: IAAA SSO (
app_id="portal2017") → portal → berserker-auth → JWT - API: JSON REST with
synjones-authheader - Constraints: Requires mobile UA (
PKUANDROID) andhttp1_only()(server rejects HTTP/2)
Key Source Files
src/main.rs— Clap CLI with subcommandssrc/commands.rs— Command implementationssrc/api.rs— API client with synjones-auth header injectionsrc/display.rs— Terminal output, QR code renderingsrc/client.rs— reqwest client with mobile UA and HTTP/1.1 enforcement
CLI Commands
| Command | Alias | Function |
|---|---|---|
login / logout / status | IAAA → portal → berserker → JWT | |
info | Card balance and details | |
pay | Display payment QR code in terminal | |
recharge | Top up card balance | |
bills | ls | Transaction history (pagination, monthly filter) |
stats | Monthly spending statistics | |
otp | TOTP 2FA management |
Auto-Login for AI Agents
# Check session status
info-auth check
# Auto-login (reads credentials from OS keyring, no password needed)
campuscard login -p
Development Notes
- The auth chain is the most complex: IAAA → portal → berserker-auth → JWT token
- Must use mobile User-Agent (
PKUANDROID) or requests will be rejected - Must use
http1_only()— the Synjones server does not support HTTP/2 - QR code for payment displayed via
info_common::qr(viuer or system viewer) - All user-facing strings in Chinese
- Error handling:
anyhow::Resultwith.context("中文描述") - Session persisted to
~/.config/info/campuscard/ - Credentials resolved via
info_common::credential(keyring → env → interactive)