Greasy Fork 支持简体中文。

安徽大学一卡通快捷显示付款二维码

先配置用户名密码,打开 https://ycard.ahu.edu.cn/ (建议设置为浏览器首页)(Via可用)

// ==UserScript==
// @name         安徽大学一卡通快捷显示付款二维码
// @namespace    BrokenClient
// @version      2.9.1
// @description  先配置用户名密码,打开 https://ycard.ahu.edu.cn/ (建议设置为浏览器首页)(Via可用)
// @author       BrokenClient
// @match        https://ycard.ahu.edu.cn/*
// @grant        none
// @run-at       document-end
// @license      MIT
// ==/UserScript==

// 2.9.1 更新说明 优化存储策略

// 在这里配置 用户名 密码
var username = "";
var password = "";

var qrcode_img, token, qrcode, cardAccount;
cardAccount = localStorage.getItem("cardAccount");

if (username && password) {
    localStorage.setItem("username", username);
    localStorage.setItem("password", password);
} else {
    username = localStorage.getItem("username");
    password = localStorage.getItem("password");
}

if (username && password) {
    // 跳转到主网址
    if (location.href != "https://ycard.ahu.edu.cn/") {
        location.replace("https://ycard.ahu.edu.cn/");
    }

    // 加载QRCode.js
    let _ele_qrcodejs = document.createElement("script");
    _ele_qrcodejs.src =
        "https://cdn.jsdelivr.net/npm/[email protected]/qrcode.min.js";
    _ele_qrcodejs.onload = ready;
    document.head.appendChild(_ele_qrcodejs);

    // 适配深色模式
    let _ele_scheme = document.createElement("meta");
    _ele_scheme.name = "color-scheme";
    _ele_scheme.content = "only light";
    document.head.appendChild(_ele_scheme);
    let _ele_wc = document.createElement("canvas");
    _ele_wc.style = "width:100%;height:100%;";
    var ctx = _ele_wc.getContext("2d");
    ctx.fillStyle = "white";
    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    document.body.appendChild(_ele_wc);

    // 禁止页面缩放
    let _ele_viewport = document.createElement("meta");
    _ele_viewport.name = "viewport";
    _ele_viewport.content =
        "width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0";
    document.head.appendChild(_ele_viewport);

    // 移除原先元素
    let _ele_center = document.getElementsByTagName("center");
    while (_ele_center.length) {
        _ele_center[0].remove();
    }

    // 加载二维码元素
    let _ele_divqrcode = document.createElement("div");
    _ele_divqrcode.id = "qrcode";
    _ele_divqrcode.style =
        "position:absolute;width:80%;height:80wh;top:5rem;left:10%;";
    _ele_divqrcode.onclick = function () {
        main(); // 协议分析barcode会过滤发送,选择重新获取barcode包
    };
    document.body.appendChild(_ele_divqrcode);
}

// QRCode.js 加载完毕后执行
function ready() {
    qrcode_img = new QRCode("qrcode", {
        text: " ",
        width: 0.8 * window.innerWidth,
        height: 0.8 * window.innerWidth,
    });

    main(); // 启动主函数
}

// 主函数
async function main() {
    if (!token) {
        token = await get_token();
        if (token) {
            console.log("token", token);
        } else {
            return 1;
        }
    }

    if (!cardAccount) {
        cardAccount = await get_cardAccount(token);
        console.log("card", cardAccount);
        localStorage.setItem("cardAccount", cardAccount);
    }

    let qrcodes = await get_qrcodes(token, cardAccount);
    qrcode = qrcodes[0];
    console.log("qrcode", qrcode);
    qrcode_img.makeCode(qrcode);

    let ws_data = {
        appCode: "mobile_service_platform",
        module: "qrcode_ykt",
        userId: qrcode,
    };
    let ws = new WebSocket(
        "wss://ycard.ahu.edu.cn/websocket/mobile_service_platform/qrcode_ykt/payCode"
    );
    ws.onopen = function (params) {
        let s = JSON.stringify(ws_data);
        console.log("send", s);
        ws.send(s);
        ws.close();
    };
}

//异常处理
function handle_error(resp) {
    if (String(resp.status)[0] == "4") {
        let j = JSON.parse(resp.responseText);
        alert(j["message"]);
    } else {
        alert(resp.statusText + "\n服务系统故障,请稍后尝试。");
    }
}

function get_token() {
    return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest();
        xhr.onload = function () {
            if (this.status == 200) {
                let j = JSON.parse(this.responseText);
                let ret = j["access_token"];
                resolve(ret);
            } else {
                handle_error(this);
                resolve(null);
            }
        };
        xhr.open(
            "POST",
            "https://ycard.ahu.edu.cn/berserker-auth/oauth/token",
            false,
            username,
            password
        );
        xhr.setRequestHeader(
            "Content-Type",
            "application/x-www-form-urlencoded"
        );
        xhr.setRequestHeader(
            "Authorization",
            "Basic bW9iaWxlX3NlcnZpY2VfcGxhdGZvcm06bW9iaWxlX3NlcnZpY2VfcGxhdGZvcm1fc2VjcmV0"
        );
        xhr.send(
            "username=" +
                username +
                "&password=" +
                password +
                "&grant_type=password&scope=all&loginFrom=h5&logintype=sno&device_token=h5&synAccessSource=h5"
        );
    });
}

function get_cardAccount(token) {
    return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest();
        xhr.onload = function () {
            let j = JSON.parse(this.responseText);
            let ret = j["data"]["cardAccount"];
            resolve(ret);
        };
        xhr.open(
            "GET",
            "https://ycard.ahu.edu.cn/berserker-base/user?synAccessSource=h5",
            false
        );
        xhr.setRequestHeader("synjones-auth", "bearer " + token);
        xhr.send(null);
    });
}

function get_qrcodes(token, cardAccount) {
    return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest();
        xhr.onload = function () {
            let j = JSON.parse(this.responseText);
            let ret = j["data"]["barcode"];
            resolve(ret);
        };
        xhr.open(
            "GET",
            "https://ycard.ahu.edu.cn/berserker-app/ykt/tsm/batchGetBarCodeGet?account=" +
                cardAccount +
                "&payacc=%23%23%23&paytype=1&synAccessSource=h5",
            false
        );
        xhr.setRequestHeader("synjones-auth", "bearer " + token);
        xhr.send(null);
    });
}