92451 67c85678e6 feat: 接入网商银行每日动账明细 (#831)
Co-authored-by: 92451 <924518135@qq.com>
Co-committed-by: 92451 <924518135@qq.com>
2026-11-02 20:58:42 +08:00

92 lines
2.9 KiB
JavaScript

import { execFileSync } from 'node:child_process';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { profileDirectory } from './config.mjs';
const BASE = path.dirname(fileURLToPath(import.meta.url));
const HELPER = path.join(BASE, 'cookie-protection.ps1');
const POWERSHELL = path.join(
process.env.SystemRoot || 'C:\\Windows',
'System32/WindowsPowerShell/v1.0/powershell.exe',
);
const DOMAINS = [
'.alipay.com',
'alipay.com',
'auth.alipay.com',
'b.alipay.com',
'authweb.alipay.com',
'.mybank.cn',
'mybank.cn',
'b.mybank.cn',
'fund.mybank.cn',
'login.mybank.cn',
];
function cookieFile(account) {
return path.join(profileDirectory(account), 'auth-cookies.dpapi');
}
function protect(value) {
return execFileSync(
POWERSHELL,
['-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-File', HELPER, '-Action', 'Protect'],
{ input: Buffer.from(value, 'utf8'), maxBuffer: 32 * 1024 * 1024, windowsHide: true },
).toString('utf8').trim();
}
function unprotect(value) {
return execFileSync(
POWERSHELL,
['-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-File', HELPER, '-Action', 'Unprotect'],
{ input: Buffer.from(value, 'utf8'), maxBuffer: 32 * 1024 * 1024, windowsHide: true },
).toString('utf8').trim();
}
function allowed(cookie) {
const domain = String(cookie.domain || '').toLowerCase();
return DOMAINS.some((item) => domain === item || domain.endsWith(item));
}
export async function saveCookies(cdp, account) {
const payload = await cdp.send('Storage.getCookies');
const cookies = (payload.cookies || []).filter(allowed);
if (cookies.length === 0) return false;
const file = cookieFile(account);
fs.mkdirSync(path.dirname(file), { recursive: true });
const encrypted = protect(Buffer.from(JSON.stringify(cookies), 'utf8').toString('base64'));
const temporary = file + '.tmp';
fs.writeFileSync(temporary, encrypted + '\r\n', { encoding: 'utf8', mode: 0o600 });
fs.renameSync(temporary, file);
return true;
}
export async function restoreCookies(cdp, account) {
const file = cookieFile(account);
if (!fs.existsSync(file)) return false;
try {
const encrypted = fs.readFileSync(file, 'utf8').trim();
const json = Buffer.from(unprotect(encrypted), 'base64').toString('utf8');
const cookies = JSON.parse(json);
if (!Array.isArray(cookies) || cookies.length === 0) return false;
const allowedKeys = [
'name', 'value', 'domain', 'path', 'expires', 'httpOnly', 'secure',
'sameSite', 'priority', 'sameParty', 'sourceScheme', 'sourcePort',
];
await cdp.send('Storage.setCookies', {
cookies: cookies.map((cookie) => Object.fromEntries(
allowedKeys
.filter((key) => cookie[key] !== undefined)
.map((key) => [key, cookie[key]]),
)),
});
return true;
} catch {
return false;
}
}