Skip to main content

bilibili

扫码登陆

核心原理:

  • 通过api获取登陆链接,oauthKey
  • 通过登录链接生成二维码
  • 通过轮询oauthKey判断是否登陆成功,成功后记录状态到scanStatus变量

获取二维码

// 访问bilibili接口,生成二维码
const generateQRcodeAPI = 'https://passport.bilibili.com/x/passport-login/web/qrcode/generate'
const { body } = await window.electron.got(generateQRcodeAPI, { responseType: 'json' })

// 生成登陆二维码
import qrCode from 'qrcode'
imageBase64.value = await qrCode.toDataURL(body.data.url, { margin: 0, errorCorrectionLevel: 'H', width: 400 })

// 记录oauthKey
oauthKey = body.data.qrcode_key

获取扫码后的数据

// 定义常量
const QRCodeAPI = 'https://passport.bilibili.com/x/passport-login/web/qrcode/poll';

// 定义状态码常量
const StatusCode = {
NOT_SCANNED: 86101,
SCANNED_NOT_CONFIRMED: 86090,
QRCODE_EXPIRED: 86038,
LOGIN_SUCCESS: 0,
ERROR_DEFAULT: -999999
};

// 定义状态枚举
enum ScanStatus {
NOT_SCANNED = 0,
SCANNED_NOT_CONFIRMED = 1,
LOGIN_SUCCESS = 2,
}

// 定义依赖的响应类型
interface ResponseBody {
code: number;
data?: {
url?: string;
};
}

// 定义依赖的全局状态
let isCheck: boolean = true; // 假设这是一个全局状态,用于控制检查流程
let scanStatus: ScanStatus = ScanStatus.NOT_SCANNED; // 假设这是扫描状态的全局状态
let checkStatusTimer: NodeJS.Timeout | null = null; // 假设这是定时器的全局状态
let QRSESSDATA: string = ''; // 假设这是SESSDATA的全局状态

// 定义检查扫描状态的函数
const checkScanStatus = async (oauthKey: string) => {
try {
const response = await window.electron.got(QRCodeAPI, {
method: 'GET',
responseType: 'json',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
searchParams: {
qrcode_key: oauthKey
}
});

const { body } = response;
const defaultData: ResponseBody = {
code: StatusCode.ERROR_DEFAULT
};
const { data = defaultData } = body;

console.log(data);

// 非扫码登录成功
if (data.code !== StatusCode.LOGIN_SUCCESS) {
switch (data.code) {
case StatusCode.NOT_SCANNED:
scanStatus = ScanStatus.NOT_SCANNED;
break;
case StatusCode.SCANNED_NOT_CONFIRMED:
scanStatus = ScanStatus.SCANNED_NOT_CONFIRMED;
break;
// 其他错误状态可以在这里处理
}

if (visible.value) { // 假设visible是一个全局状态,用于控制是否可见
checkStatusTimer = setTimeout(() => {
checkScanStatus(oauthKey);
}, 3000);
}

return;
}

// 获取SESSDATA
const sessDataMatch = body.data.url?.match(/SESSDATA=(\S*)&bili_jct/);
if (sessDataMatch) {
QRSESSDATA = sessDataMatch[1];
}

scanStatus = ScanStatus.LOGIN_SUCCESS;
isCheck = false;
} catch (e) {
console.error(e);
}
};

// 假设visible是一个全局状态,用于控制是否可见
let visible: { value: boolean } = { value: true };

// 调用函数开始检查
checkScanStatus('your_oauth_key');