# QR Login: Account List API Failure Fallback

**Date**: 2026-07-24
**Symptom**: User scans QR code, QR disappears, but `werss:login:status` stays at `0` in Redis. System reports as not logged in despite scan succeeding.

## Root Cause Chain

```
User scans QR → polling detects status=1 (success)
  → _handle_login_success()
    → _extract_login_info()       ✓ token + cookies extracted successfully
    → _clean_qr_code()            ✓ QR file deleted
    → _get_account_info()
      → _get_account_list()
        → GET /cgi-bin/switchacct?action=get_acct_list
        → Response: {"base_resp": {"ret": 200002, "err_msg": "invalid args"}}
        → returns None ✗
      → returns None ✗
    → if None: return False ✗     # login_callback NEVER called!
  → werss:login:status stays at "0"
```

The `/cgi-bin/switchacct` API with `action=get_acct_list` parameter appears to have changed on WeChat's side, returning `ret: 200002` for requests that previously worked.

## Verifying the Issue

### Log Evidence
```bash
journalctl -u we-mp-rss --no-pager | grep "获取账号列表失败"
# → WARNING:driver.wx_api:获取账号列表失败: {'ret': 200002, 'err_msg': 'invalid args'}
```

### Redis vs API Discrepancy
```python
# API says True (reading in-memory _islogin flag)
GET /api/v1/wx/auth/qr/status → {"login_status": true, "qr_code": false}

# Redis says 0 (callback never fired)
redis-cli GET werss:login:status → "0"
```

### Session Wipe Evidence
If multiple QR code generations occurred, the session state may have been wiped by `self.__init__()` called inside `get_qr_code()`:
```python
from driver.wx_api import WeChat_api
WeChat_api._islogin  # False (wiped)
WeChat_api.token     # None (wiped)
```

## Fix Applied

**File**: `driver/wx_api.py`, method `_handle_login_success()` (line ~464)

The method now handles the case where `_get_account_info()` returns `None` by manually saving the token/cookies to Redis:

```python
def _handle_login_success(self):
    try:
        self.is_logged_in = True
        self._extract_login_info()
        self._clean_qr_code()
        
        # Try account info (may fail due to API changes)
        account_info = self._get_account_info()
        if account_info is not None:
            print_success("登录成功！")
            return True
        
        # FALLBACK: account list API failed but token/cookies exist
        if self.token and self.session.cookies:
            print_warning("账号列表获取失败，但token/cookie已获取，保存登录状态")
            from driver.cookies import expire
            from driver.token import set_token as _set_token
            from driver.success import setStatus
            from driver.store import Store
            
            cookies_list = self._convert_cookies_to_list()
            Store.save(cookies_list)
            
            fallback_info = {
                'wx_app_name': '微信公众号(unknown)',
                'wx_logo': '', 'wx_read_yesterday': 0,
                'wx_share_yesterday': 0, 'wx_watch_yesterday': 0,
                'wx_yuan_count': 0, 'wx_user_count': 0
            }
            
            login_data = {
                'cookies': self.cookies,
                'cookies_str': self._format_cookies_string(),
                'token': self.token,
                'fingerprint': self.fingerprint,
                'wx_login_url': self.qr_code_path,
                'expiry': expire(self.cookies_dict if self.cookies_dict else cookies_list)
            }
            
            _set_token(login_data, fallback_info)
            setStatus(True)
            
            if self.login_callback:
                self.login_callback(login_data, fallback_info)
            
            print_success("登录信息已保存（账号列表API不可用，已fallback）")
            return True
        
        return False
    except Exception as e:
        print_error(f"处理登录失败: {str(e)}")
        return False
```

## Service Restart Required

After applying the fix:
```bash
sudo systemctl restart we-mp-rss
# Then delete old QR and lock files before generating new QR:
rm -f /home/ubuntu/project/we-mp-rss-main/static/wx_qrcode.png
rm -f /home/ubuntu/project/we-mp-rss-main/data/lock.lock
```
