dasdasd
This commit is contained in:
parent
0fef5d7f74
commit
d4cc237ccd
120
browser-automation-ts/analyze-advanced.js
Normal file
120
browser-automation-ts/analyze-advanced.js
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/**
|
||||||
|
* 高级分析:找出"成功模式"而不是"成功BIN"
|
||||||
|
* 目标:在保持BIN多样性的同时,提高成功率
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 70张成功卡号
|
||||||
|
const fullCards = [
|
||||||
|
// 原始16张
|
||||||
|
'6228367545055812', '6228367548774419', '6228367546781457', '6228367542738949',
|
||||||
|
'6228367542602400', '6228367548575105', '6228367546496080', '6228367540057649',
|
||||||
|
'6228367549574719', '6228367548435128', '6228367542797374', '6228367545956423',
|
||||||
|
'6228367547237848', '6228367540385107', '6228367544252006', '6228367547562054',
|
||||||
|
// 今天54张
|
||||||
|
'6228367541130577', '6228367540744030', '6228367549888788', '6228367549131205',
|
||||||
|
'6228367541450744', '6228367547238010', '6228367547300364', '6228367540814288',
|
||||||
|
'6228367546042579', '6228367546361755', '6228367542443235', '6228367543564435',
|
||||||
|
'6228367548400627', '6228367544445204', '6228367542653734', '6228367549976732',
|
||||||
|
'6228367540810302', '6228367540707201', '6228367545237808', '6228367544322734',
|
||||||
|
'6228367541880148', '6228367549130520', '6228367547863197', '6228367541210049',
|
||||||
|
'6228367549031561', '6228367542464926', '6228367542487000', '6228367545452860',
|
||||||
|
'6228367548491592', '6228367545022853', '6228367545864858', '6228367544742832',
|
||||||
|
'6228367540023658', '6228367547416988', '6228367547093159', '6228367549198576',
|
||||||
|
'6228367548160064', '6228367546223252', '6228367544873785', '6228367541299976',
|
||||||
|
'6228367542940032', '6228367546998937', '6228367545800241', '6228367543770784',
|
||||||
|
'6228367545976843', '6228367547542551', '6228367543917914', '6228367545657930',
|
||||||
|
'6228367586381796', '6228367544322809', '6228367549131254', '6228367543917146',
|
||||||
|
'6228367546998903', '6228367545864460'
|
||||||
|
];
|
||||||
|
|
||||||
|
console.log('=== 高级分析:成功模式识别 ===\n');
|
||||||
|
|
||||||
|
// 分析1:BIN的第10-12位(extension)的规律
|
||||||
|
console.log('1. BIN Extension(第10-12位)分析:\n');
|
||||||
|
const extensions = {};
|
||||||
|
fullCards.forEach(card => {
|
||||||
|
const ext = card.slice(9, 12); // 第10-12位
|
||||||
|
extensions[ext] = (extensions[ext] || 0) + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
const sortedExt = Object.entries(extensions)
|
||||||
|
.sort((a, b) => b[1] - a[1])
|
||||||
|
.slice(0, 10);
|
||||||
|
|
||||||
|
sortedExt.forEach(([ext, count]) => {
|
||||||
|
const percent = (count / 70 * 100).toFixed(1);
|
||||||
|
console.log(` ${ext}: ${count}次 (${percent}%)`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 分析2:完整BIN(13位)的第13位规律
|
||||||
|
console.log('\n2. BIN最后一位(第13位)分析:\n');
|
||||||
|
const lastDigits = {};
|
||||||
|
fullCards.forEach(card => {
|
||||||
|
const last = card[12]; // 第13位
|
||||||
|
lastDigits[last] = (lastDigits[last] || 0) + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let i = 0; i <= 9; i++) {
|
||||||
|
const count = lastDigits[i] || 0;
|
||||||
|
const percent = (count / 70 * 100).toFixed(1);
|
||||||
|
console.log(` ${i}: ${count}次 (${percent}%)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分析3:后3位数字的"和"的规律
|
||||||
|
console.log('\n3. 后3位数字之和的分布:\n');
|
||||||
|
const sums = {};
|
||||||
|
fullCards.forEach(card => {
|
||||||
|
const last3 = card.slice(-4, -1);
|
||||||
|
const sum = parseInt(last3[0]) + parseInt(last3[1]) + parseInt(last3[2]);
|
||||||
|
sums[sum] = (sums[sum] || 0) + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
const sortedSums = Object.entries(sums)
|
||||||
|
.sort((a, b) => b[1] - a[1])
|
||||||
|
.slice(0, 10);
|
||||||
|
|
||||||
|
sortedSums.forEach(([sum, count]) => {
|
||||||
|
const percent = (count / 70 * 100).toFixed(1);
|
||||||
|
console.log(` 和=${sum}: ${count}次 (${percent}%)`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 分析4:后3位数字的"奇偶性"规律
|
||||||
|
console.log('\n4. 后3位奇偶性分析:\n');
|
||||||
|
const patterns = {
|
||||||
|
'偶偶偶': 0, '偶偶奇': 0, '偶奇偶': 0, '偶奇奇': 0,
|
||||||
|
'奇偶偶': 0, '奇偶奇': 0, '奇奇偶': 0, '奇奇奇': 0
|
||||||
|
};
|
||||||
|
|
||||||
|
fullCards.forEach(card => {
|
||||||
|
const last3 = card.slice(-4, -1);
|
||||||
|
const pattern = last3.split('').map(d => parseInt(d) % 2 === 0 ? '偶' : '奇').join('');
|
||||||
|
patterns[pattern]++;
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.entries(patterns)
|
||||||
|
.sort((a, b) => b[1] - a[1])
|
||||||
|
.forEach(([pattern, count]) => {
|
||||||
|
const percent = (count / 70 * 100).toFixed(1);
|
||||||
|
console.log(` ${pattern}: ${count}次 (${percent}%)`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 分析5:Luhn校验位的分布
|
||||||
|
console.log('\n5. Luhn校验位(最后一位)分布:\n');
|
||||||
|
const checkDigits = {};
|
||||||
|
fullCards.forEach(card => {
|
||||||
|
const check = card[15]; // 最后一位
|
||||||
|
checkDigits[check] = (checkDigits[check] || 0) + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let i = 0; i <= 9; i++) {
|
||||||
|
const count = checkDigits[i] || 0;
|
||||||
|
const percent = (count / 70 * 100).toFixed(1);
|
||||||
|
console.log(` ${i}: ${count}次 (${percent}%)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n=== 关键发现 ===\n');
|
||||||
|
console.log('基于以上分析,可以优化生成策略:');
|
||||||
|
console.log('1. 优先选择高频的BIN Extension');
|
||||||
|
console.log('2. 后3位数字之和倾向于某些值');
|
||||||
|
console.log('3. 奇偶性组合有明显偏好');
|
||||||
|
console.log('4. 结合马尔可夫链,在保持BIN多样性的同时提高成功率');
|
||||||
90
browser-automation-ts/analyze-clustering.js
Normal file
90
browser-automation-ts/analyze-clustering.js
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/**
|
||||||
|
* 聚类分析 - 找出成功案例的"家族"模式
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 70张成功卡号
|
||||||
|
const fullCards = [
|
||||||
|
// 原始16张
|
||||||
|
'6228367545055812', '6228367548774419', '6228367546781457', '6228367542738949',
|
||||||
|
'6228367542602400', '6228367548575105', '6228367546496080', '6228367540057649',
|
||||||
|
'6228367549574719', '6228367548435128', '6228367542797374', '6228367545956423',
|
||||||
|
'6228367547237848', '6228367540385107', '6228367544252006', '6228367547562054',
|
||||||
|
// 今天54张
|
||||||
|
'6228367541130577', '6228367540744030', '6228367549888788', '6228367549131205',
|
||||||
|
'6228367541450744', '6228367547238010', '6228367547300364', '6228367540814288',
|
||||||
|
'6228367546042579', '6228367546361755', '6228367542443235', '6228367543564435',
|
||||||
|
'6228367548400627', '6228367544445204', '6228367542653734', '6228367549976732',
|
||||||
|
'6228367540810302', '6228367540707201', '6228367545237808', '6228367544322734',
|
||||||
|
'6228367541880148', '6228367549130520', '6228367547863197', '6228367541210049',
|
||||||
|
'6228367549031561', '6228367542464926', '6228367542487000', '6228367545452860',
|
||||||
|
'6228367548491592', '6228367545022853', '6228367545864858', '6228367544742832',
|
||||||
|
'6228367540023658', '6228367547416988', '6228367547093159', '6228367549198576',
|
||||||
|
'6228367548160064', '6228367546223252', '6228367544873785', '6228367541299976',
|
||||||
|
'6228367542940032', '6228367546998937', '6228367545800241', '6228367543770784',
|
||||||
|
'6228367545976843', '6228367547542551', '6228367543917914', '6228367545657930',
|
||||||
|
'6228367586381796', '6228367544322809', '6228367549131254', '6228367543917146',
|
||||||
|
'6228367546998903', '6228367545864460'
|
||||||
|
];
|
||||||
|
|
||||||
|
console.log('=== 聚类分析:找出成功案例的家族 ===\n');
|
||||||
|
|
||||||
|
// 提取BIN(13位前缀)
|
||||||
|
const binGroups = {};
|
||||||
|
fullCards.forEach(card => {
|
||||||
|
const bin = card.slice(0, 13);
|
||||||
|
if (!binGroups[bin]) {
|
||||||
|
binGroups[bin] = [];
|
||||||
|
}
|
||||||
|
binGroups[bin].push(card);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 按数量排序
|
||||||
|
const sortedBins = Object.entries(binGroups)
|
||||||
|
.sort((a, b) => b[1].length - a[1].length);
|
||||||
|
|
||||||
|
console.log('=== BIN家族分布(前10个) ===\n');
|
||||||
|
sortedBins.slice(0, 10).forEach(([bin, cards], i) => {
|
||||||
|
console.log(`${i + 1}. BIN: ${bin} (${cards.length}张)`);
|
||||||
|
cards.forEach(card => {
|
||||||
|
const last3 = card.slice(-4, -1);
|
||||||
|
console.log(` ${card} -> 后3位: ${last3}`);
|
||||||
|
});
|
||||||
|
console.log();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 分析每个BIN家族的后3位模式
|
||||||
|
console.log('=== 每个BIN家族的后3位规律 ===\n');
|
||||||
|
sortedBins.slice(0, 10).forEach(([bin, cards]) => {
|
||||||
|
if (cards.length < 2) return;
|
||||||
|
|
||||||
|
console.log(`BIN: ${bin} (${cards.length}张)`);
|
||||||
|
|
||||||
|
const last3s = cards.map(c => c.slice(-4, -1));
|
||||||
|
|
||||||
|
// 统计每位的分布
|
||||||
|
const pos1 = {}, pos2 = {};
|
||||||
|
last3s.forEach(l3 => {
|
||||||
|
pos1[l3[0]] = (pos1[l3[0]] || 0) + 1;
|
||||||
|
pos2[l3[1]] = (pos2[l3[1]] || 0) + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(' 百位分布:', Object.entries(pos1).sort((a, b) => b[1] - a[1]).map(([d, c]) => `${d}:${c}`).join(', '));
|
||||||
|
console.log(' 十位分布:', Object.entries(pos2).sort((a, b) => b[1] - a[1]).map(([d, c]) => `${d}:${c}`).join(', '));
|
||||||
|
console.log();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 找出"热门BIN"(成功率高的BIN)
|
||||||
|
console.log('=== 热门BIN推荐(成功案例>=2张)===\n');
|
||||||
|
const hotBins = sortedBins.filter(([_, cards]) => cards.length >= 2);
|
||||||
|
console.log(`共找到 ${hotBins.length} 个热门BIN\n`);
|
||||||
|
|
||||||
|
hotBins.forEach(([bin, cards]) => {
|
||||||
|
const last3s = cards.map(c => c.slice(-4, -1));
|
||||||
|
console.log(`${bin}: ${last3s.join(', ')}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 生成配置建议
|
||||||
|
console.log('\n=== 优化建议 ===\n');
|
||||||
|
console.log(`1. 优先使用热门BIN(${hotBins.length}个),它们的成功率更高`);
|
||||||
|
console.log(`2. 对于热门BIN,可以直接从已知成功的后3位变异生成`);
|
||||||
|
console.log(`3. 冷门BIN(只有1张成功)可以降低权重或跳过`);
|
||||||
93
browser-automation-ts/analyze-markov.js
Normal file
93
browser-automation-ts/analyze-markov.js
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/**
|
||||||
|
* 马尔可夫链分析 - 分析位置之间的转移概率
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 70张成功卡号
|
||||||
|
const fullCards = [
|
||||||
|
// 原始16张
|
||||||
|
'6228367545055812', '6228367548774419', '6228367546781457', '6228367542738949',
|
||||||
|
'6228367542602400', '6228367548575105', '6228367546496080', '6228367540057649',
|
||||||
|
'6228367549574719', '6228367548435128', '6228367542797374', '6228367545956423',
|
||||||
|
'6228367547237848', '6228367540385107', '6228367544252006', '6228367547562054',
|
||||||
|
// 今天54张
|
||||||
|
'6228367541130577', '6228367540744030', '6228367549888788', '6228367549131205',
|
||||||
|
'6228367541450744', '6228367547238010', '6228367547300364', '6228367540814288',
|
||||||
|
'6228367546042579', '6228367546361755', '6228367542443235', '6228367543564435',
|
||||||
|
'6228367548400627', '6228367544445204', '6228367542653734', '6228367549976732',
|
||||||
|
'6228367540810302', '6228367540707201', '6228367545237808', '6228367544322734',
|
||||||
|
'6228367541880148', '6228367549130520', '6228367547863197', '6228367541210049',
|
||||||
|
'6228367549031561', '6228367542464926', '6228367542487000', '6228367545452860',
|
||||||
|
'6228367548491592', '6228367545022853', '6228367545864858', '6228367544742832',
|
||||||
|
'6228367540023658', '6228367547416988', '6228367547093159', '6228367549198576',
|
||||||
|
'6228367548160064', '6228367546223252', '6228367544873785', '6228367541299976',
|
||||||
|
'6228367542940032', '6228367546998937', '6228367545800241', '6228367543770784',
|
||||||
|
'6228367545976843', '6228367547542551', '6228367543917914', '6228367545657930',
|
||||||
|
'6228367586381796', '6228367544322809', '6228367549131254', '6228367543917146',
|
||||||
|
'6228367546998903', '6228367545864460'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 提取后3位(不含校验位)
|
||||||
|
const patterns = fullCards.map(card => card.slice(-4, -1));
|
||||||
|
|
||||||
|
console.log('=== 马尔可夫链分析:位置转移概率 ===\n');
|
||||||
|
|
||||||
|
// 统计转移概率:百位 -> 十位
|
||||||
|
const transitions = {};
|
||||||
|
|
||||||
|
patterns.forEach(p => {
|
||||||
|
const d1 = p[0]; // 百位
|
||||||
|
const d2 = p[1]; // 十位
|
||||||
|
|
||||||
|
if (!transitions[d1]) {
|
||||||
|
transitions[d1] = {};
|
||||||
|
}
|
||||||
|
transitions[d1][d2] = (transitions[d1][d2] || 0) + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 打印转移概率矩阵
|
||||||
|
console.log('百位 -> 十位 转移概率:\n');
|
||||||
|
for (let i = 0; i <= 9; i++) {
|
||||||
|
if (!transitions[i]) continue;
|
||||||
|
|
||||||
|
const total = Object.values(transitions[i]).reduce((sum, count) => sum + count, 0);
|
||||||
|
console.log(`百位=${i} (${total}次):`);
|
||||||
|
|
||||||
|
const sorted = Object.entries(transitions[i])
|
||||||
|
.sort((a, b) => b[1] - a[1])
|
||||||
|
.slice(0, 5); // 只显示前5个最高概率
|
||||||
|
|
||||||
|
sorted.forEach(([digit, count]) => {
|
||||||
|
const prob = (count / total * 100).toFixed(1);
|
||||||
|
console.log(` -> ${digit}: ${count}次 (${prob}%)`);
|
||||||
|
});
|
||||||
|
console.log();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成转移概率配置
|
||||||
|
console.log('\n=== 生成马尔可夫转移配置 ===\n');
|
||||||
|
console.log('const markovTransitions = {');
|
||||||
|
for (let i = 0; i <= 9; i++) {
|
||||||
|
if (!transitions[i]) {
|
||||||
|
console.log(` '${i}': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], // 无数据,均匀分布`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const weights = Array.from({length: 10}, (_, j) => transitions[i][j] || 0);
|
||||||
|
console.log(` '${i}': [${weights.join(', ')}],`);
|
||||||
|
}
|
||||||
|
console.log('};');
|
||||||
|
|
||||||
|
// 分析是否有明显的模式
|
||||||
|
console.log('\n=== 关键发现 ===\n');
|
||||||
|
for (let i = 0; i <= 9; i++) {
|
||||||
|
if (!transitions[i]) continue;
|
||||||
|
|
||||||
|
const total = Object.values(transitions[i]).reduce((sum, count) => sum + count, 0);
|
||||||
|
const max = Math.max(...Object.values(transitions[i]));
|
||||||
|
const maxDigit = Object.entries(transitions[i]).find(([_, count]) => count === max)[0];
|
||||||
|
const maxProb = (max / total * 100).toFixed(1);
|
||||||
|
|
||||||
|
if (maxProb > 25) {
|
||||||
|
console.log(`⚠️ 百位=${i} 时,十位=${maxDigit} 的概率高达 ${maxProb}%`);
|
||||||
|
}
|
||||||
|
}
|
||||||
61
browser-automation-ts/analyze-patterns.js
Normal file
61
browser-automation-ts/analyze-patterns.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// 分析成功卡号的规律(完整16位卡号)
|
||||||
|
const fullCards = [
|
||||||
|
// 原始16张
|
||||||
|
'6228367545055812', '6228367548774419', '6228367546781457', '6228367542738949',
|
||||||
|
'6228367542602400', '6228367548575105', '6228367546496080', '6228367540057649',
|
||||||
|
'6228367549574719', '6228367548435128', '6228367542797374', '6228367545956423',
|
||||||
|
'6228367547237848', '6228367540385107', '6228367544252006', '6228367547562054',
|
||||||
|
// 今天54张
|
||||||
|
'6228367541130577', '6228367540744030', '6228367549888788', '6228367549131205',
|
||||||
|
'6228367541450744', '6228367547238010', '6228367547300364', '6228367540814288',
|
||||||
|
'6228367546042579', '6228367546361755', '6228367542443235', '6228367543564435',
|
||||||
|
'6228367548400627', '6228367544445204', '6228367542653734', '6228367549976732',
|
||||||
|
'6228367540810302', '6228367540707201', '6228367545237808', '6228367544322734',
|
||||||
|
'6228367541880148', '6228367549130520', '6228367547863197', '6228367541210049',
|
||||||
|
'6228367549031561', '6228367542464926', '6228367542487000', '6228367545452860',
|
||||||
|
'6228367548491592', '6228367545022853', '6228367545864858', '6228367544742832',
|
||||||
|
'6228367540023658', '6228367547416988', '6228367547093159', '6228367549198576',
|
||||||
|
'6228367548160064', '6228367546223252', '6228367544873785', '6228367541299976',
|
||||||
|
'6228367542940032', '6228367546998937', '6228367545800241', '6228367543770784',
|
||||||
|
'6228367545976843', '6228367547542551', '6228367543917914', '6228367545657930',
|
||||||
|
'6228367586381796', '6228367544322809', '6228367549131254', '6228367543917146',
|
||||||
|
'6228367546998903', '6228367545864460'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 提取后3位(不含校验位)
|
||||||
|
const patterns = fullCards.map(card => card.slice(-4, -1));
|
||||||
|
|
||||||
|
// 统计每个位置的数字频率
|
||||||
|
const pos1 = {}; // 百位
|
||||||
|
const pos2 = {}; // 十位
|
||||||
|
|
||||||
|
patterns.forEach(p => {
|
||||||
|
const d1 = p[0];
|
||||||
|
const d2 = p[1];
|
||||||
|
|
||||||
|
pos1[d1] = (pos1[d1] || 0) + 1;
|
||||||
|
pos2[d2] = (pos2[d2] || 0) + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('=== 70张成功卡号的数字分布规律 ===\n');
|
||||||
|
|
||||||
|
console.log('位置1(千位)频率:');
|
||||||
|
for (let i = 0; i <= 9; i++) {
|
||||||
|
const count = pos1[i] || 0;
|
||||||
|
const percent = (count / patterns.length * 100).toFixed(1);
|
||||||
|
console.log(` ${i}: ${count}次 (${percent}%)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n位置2(十位)频率:');
|
||||||
|
for (let i = 0; i <= 9; i++) {
|
||||||
|
const count = pos2[i] || 0;
|
||||||
|
const percent = (count / patterns.length * 100).toFixed(1);
|
||||||
|
console.log(` ${i}: ${count}次 (${percent}%)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成权重数组(用于config.ts)- 只需要2位
|
||||||
|
console.log('\n=== 生成权重配置(后2位,不含校验位)===\n');
|
||||||
|
console.log('const positionWeights = [');
|
||||||
|
console.log(' [' + Array.from({length: 10}, (_, i) => pos1[i] || 0).join(', ') + '], // 百位');
|
||||||
|
console.log(' [' + Array.from({length: 10}, (_, i) => pos2[i] || 0).join(', ') + '] // 十位');
|
||||||
|
console.log('];');
|
||||||
@ -1,27 +1,27 @@
|
|||||||
# Windsurf 注册自动化配置
|
# Windsurf 注册自动化配置
|
||||||
site:
|
site:
|
||||||
name: Windsurf
|
name: Windsurf
|
||||||
url: https://windsurf.com/refer?referral_code=55424ec434
|
url: https://windsurf.com/account/register
|
||||||
|
|
||||||
# 工作流定义
|
# 工作流定义
|
||||||
workflow:
|
workflow:
|
||||||
# ==================== 步骤 0: 处理邀请链接 ====================
|
# ==================== 步骤 0: 处理邀请链接 ====================
|
||||||
- action: navigate
|
# - action: navigate
|
||||||
name: "打开邀请链接"
|
# name: "打开邀请链接"
|
||||||
url: "https://windsurf.com/refer?referral_code=55424ec434"
|
# url: "https://windsurf.com/refer?referral_code=55424ec434"
|
||||||
options:
|
# options:
|
||||||
waitUntil: 'networkidle2'
|
# waitUntil: 'networkidle2'
|
||||||
timeout: 30000
|
# timeout: 30000
|
||||||
|
#
|
||||||
- action: click
|
# - action: click
|
||||||
name: "点击接受邀请"
|
# name: "点击接受邀请"
|
||||||
selector:
|
# selector:
|
||||||
- text: 'Sign up to accept referral'
|
# - text: 'Sign up to accept referral'
|
||||||
selector: 'button'
|
# selector: 'button'
|
||||||
- css: 'button.bg-sk-aqua'
|
# - css: 'button.bg-sk-aqua'
|
||||||
- css: 'button:has-text("Sign up to accept referral")'
|
# - css: 'button:has-text("Sign up to accept referral")'
|
||||||
timeout: 30000
|
# timeout: 30000
|
||||||
waitForNavigation: true
|
# waitForNavigation: true
|
||||||
|
|
||||||
# 验证跳转到注册页面(带referral_code)
|
# 验证跳转到注册页面(带referral_code)
|
||||||
- action: verify
|
- action: verify
|
||||||
|
|||||||
0
browser-automation-ts/docs/ANTI-FRAUD-STRATEGY.md
Normal file
0
browser-automation-ts/docs/ANTI-FRAUD-STRATEGY.md
Normal file
0
browser-automation-ts/docs/STRIPE-ANTI-FRAUD.md
Normal file
0
browser-automation-ts/docs/STRIPE-ANTI-FRAUD.md
Normal file
47
browser-automation-ts/test-bin-distribution.mjs
Normal file
47
browser-automation-ts/test-bin-distribution.mjs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* 测试BIN分布
|
||||||
|
*/
|
||||||
|
import pkg from './src/tools/card/CardGeneratorTool.js';
|
||||||
|
const { CardGeneratorTool } = pkg;
|
||||||
|
|
||||||
|
async function test() {
|
||||||
|
console.log('生成1000张卡,分析BIN分布...\n');
|
||||||
|
|
||||||
|
const cardGen = new CardGeneratorTool();
|
||||||
|
await cardGen.initialize({});
|
||||||
|
|
||||||
|
const cards = await cardGen.generateBatch(1000, 'unionpay');
|
||||||
|
|
||||||
|
// 统计BIN分布
|
||||||
|
const binCounts = {};
|
||||||
|
cards.forEach(card => {
|
||||||
|
const bin = card.number.slice(0, 13);
|
||||||
|
binCounts[bin] = (binCounts[bin] || 0) + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 排序
|
||||||
|
const sorted = Object.entries(binCounts)
|
||||||
|
.sort((a, b) => b[1] - a[1]);
|
||||||
|
|
||||||
|
console.log('=== BIN分布(前10个) ===\n');
|
||||||
|
sorted.slice(0, 10).forEach(([bin, count], i) => {
|
||||||
|
const percent = (count / 1000 * 100).toFixed(1);
|
||||||
|
const isHot = ['6228367549131', '6228367544322', '6228367545864', '6228367546998', '6228367543917'].includes(bin);
|
||||||
|
const mark = isHot ? '🔥' : ' ';
|
||||||
|
console.log(`${i + 1}. ${mark} ${bin}: ${count}次 (${percent}%)`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 统计热门BIN的总占比
|
||||||
|
const hotBins = ['6228367549131', '6228367544322', '6228367545864', '6228367546998', '6228367543917'];
|
||||||
|
const hotCount = hotBins.reduce((sum, bin) => sum + (binCounts[bin] || 0), 0);
|
||||||
|
const hotPercent = (hotCount / 1000 * 100).toFixed(1);
|
||||||
|
|
||||||
|
console.log(`\n=== 热门BIN统计 ===`);
|
||||||
|
console.log(`热门BIN总占比: ${hotCount}/1000 (${hotPercent}%)`);
|
||||||
|
console.log(`期望占比: ~${(5 * 5 / (5 * 5 + 60 * 1) * 100).toFixed(1)}% (权重5 vs 权重1)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
test().catch(err => {
|
||||||
|
console.error('错误:', err.message);
|
||||||
|
console.error(err.stack);
|
||||||
|
});
|
||||||
23
browser-automation-ts/test-card-simple.js
Normal file
23
browser-automation-ts/test-card-simple.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* 简单测试卡号生成
|
||||||
|
*/
|
||||||
|
const {CardGeneratorTool} = require('./src/tools/card/CardGeneratorTool');
|
||||||
|
|
||||||
|
async function test() {
|
||||||
|
console.log('开始测试...');
|
||||||
|
|
||||||
|
const cardGen = new CardGeneratorTool();
|
||||||
|
await cardGen.initialize({});
|
||||||
|
|
||||||
|
console.log('生成10张测试卡...\n');
|
||||||
|
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
const card = await cardGen.generate('unionpay');
|
||||||
|
console.log(`${i + 1}. ${card.number} (${card.month}/${card.year}) - ${card.issuer}-${card.cvv}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test().catch(err => {
|
||||||
|
console.error('错误:', err.message);
|
||||||
|
console.error(err.stack);
|
||||||
|
});
|
||||||
90
browser-automation-ts/test-card-validity.mjs
Normal file
90
browser-automation-ts/test-card-validity.mjs
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/**
|
||||||
|
* 测试生成的卡号是否有效
|
||||||
|
*/
|
||||||
|
import pkg from './src/tools/card/CardGeneratorTool.js';
|
||||||
|
const { CardGeneratorTool } = pkg;
|
||||||
|
|
||||||
|
// Luhn算法验证
|
||||||
|
function validateLuhn(cardNumber) {
|
||||||
|
let sum = 0;
|
||||||
|
let isEven = false;
|
||||||
|
|
||||||
|
for (let i = cardNumber.length - 1; i >= 0; i--) {
|
||||||
|
let digit = parseInt(cardNumber[i]);
|
||||||
|
|
||||||
|
if (isEven) {
|
||||||
|
digit *= 2;
|
||||||
|
if (digit > 9) digit -= 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
sum += digit;
|
||||||
|
isEven = !isEven;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum % 10 === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function test() {
|
||||||
|
console.log('生成20张卡,验证有效性...\n');
|
||||||
|
|
||||||
|
const cardGen = new CardGeneratorTool();
|
||||||
|
await cardGen.initialize({});
|
||||||
|
|
||||||
|
const cards = await cardGen.generateBatch(20, 'unionpay');
|
||||||
|
|
||||||
|
let luhnPass = 0;
|
||||||
|
let luhnFail = 0;
|
||||||
|
|
||||||
|
console.log('=== 卡号验证 ===\n');
|
||||||
|
cards.forEach((card, i) => {
|
||||||
|
const isValid = validateLuhn(card.number);
|
||||||
|
const status = isValid ? '✅' : '❌';
|
||||||
|
|
||||||
|
if (isValid) luhnPass++;
|
||||||
|
else luhnFail++;
|
||||||
|
|
||||||
|
console.log(`${i + 1}. ${status} ${card.number}`);
|
||||||
|
console.log(` 有效期: ${card.month}/${card.year}`);
|
||||||
|
console.log(` CVV: ${card.cvv}`);
|
||||||
|
console.log(` 发卡行: ${card.issuer} (${card.country})`);
|
||||||
|
console.log();
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('=== 验证结果 ===');
|
||||||
|
console.log(`Luhn校验通过: ${luhnPass}/20`);
|
||||||
|
console.log(`Luhn校验失败: ${luhnFail}/20`);
|
||||||
|
|
||||||
|
// 验证有效期范围
|
||||||
|
console.log('\n=== 有效期检查 ===');
|
||||||
|
const months = cards.map(c => parseInt(c.month));
|
||||||
|
const years = cards.map(c => parseInt(c.year));
|
||||||
|
|
||||||
|
const validMonths = months.filter(m => m >= 1 && m <= 12).length;
|
||||||
|
const validYears = years.filter(y => y >= 26 && y <= 30).length;
|
||||||
|
|
||||||
|
console.log(`月份有效: ${validMonths}/20 (范围: 01-12)`);
|
||||||
|
console.log(`年份有效: ${validYears}/20 (范围: 26-30)`);
|
||||||
|
|
||||||
|
// 验证CVV长度
|
||||||
|
console.log('\n=== CVV检查 ===');
|
||||||
|
const validCVV = cards.filter(c => c.cvv.length === 3).length;
|
||||||
|
console.log(`CVV长度正确: ${validCVV}/20 (应为3位)`);
|
||||||
|
|
||||||
|
// 显示有效期和CVV的分布
|
||||||
|
console.log('\n=== 有效期分布 ===');
|
||||||
|
const expiryDist = {};
|
||||||
|
cards.forEach(c => {
|
||||||
|
const key = `${c.month}/${c.year}`;
|
||||||
|
expiryDist[key] = (expiryDist[key] || 0) + 1;
|
||||||
|
});
|
||||||
|
Object.entries(expiryDist)
|
||||||
|
.sort((a, b) => b[1] - a[1])
|
||||||
|
.forEach(([expiry, count]) => {
|
||||||
|
console.log(` ${expiry}: ${count}次`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
test().catch(err => {
|
||||||
|
console.error('错误:', err.message);
|
||||||
|
console.error(err.stack);
|
||||||
|
});
|
||||||
74
browser-automation-ts/test-gen.mjs
Normal file
74
browser-automation-ts/test-gen.mjs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/**
|
||||||
|
* 测试卡号生成规律
|
||||||
|
*/
|
||||||
|
import pkg from './src/tools/card/CardGeneratorTool.js';
|
||||||
|
const { CardGeneratorTool } = pkg;
|
||||||
|
|
||||||
|
async function test() {
|
||||||
|
console.log('开始生成1000张卡...\n');
|
||||||
|
|
||||||
|
const cardGen = new CardGeneratorTool();
|
||||||
|
await cardGen.initialize({});
|
||||||
|
|
||||||
|
const cards = await cardGen.generateBatch(1000, 'unionpay');
|
||||||
|
|
||||||
|
// 统计后4位的分布
|
||||||
|
const pos1 = {};
|
||||||
|
const pos2 = {};
|
||||||
|
const pos3 = {};
|
||||||
|
|
||||||
|
cards.forEach(card => {
|
||||||
|
const last4 = card.number.slice(-4);
|
||||||
|
const digits = last4.slice(0, 3);
|
||||||
|
|
||||||
|
pos1[digits[0]] = (pos1[digits[0]] || 0) + 1;
|
||||||
|
pos2[digits[1]] = (pos2[digits[1]] || 0) + 1;
|
||||||
|
pos3[digits[2]] = (pos3[digits[2]] || 0) + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('=== 生成的1000张卡的数字分布 ===\n');
|
||||||
|
|
||||||
|
console.log('位置1(千位)频率:');
|
||||||
|
for (let i = 0; i <= 9; i++) {
|
||||||
|
const count = pos1[i] || 0;
|
||||||
|
const percent = (count / 1000 * 100).toFixed(1);
|
||||||
|
const expected = [14, 9, 7, 8, 10, 2, 4, 7, 7, 2][i];
|
||||||
|
const expectedPercent = (expected / 70 * 100).toFixed(1);
|
||||||
|
console.log(` ${i}: ${count}次 (${percent}%) [期望: ${expectedPercent}%]`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n位置2(百位)频率:');
|
||||||
|
for (let i = 0; i <= 9; i++) {
|
||||||
|
const count = pos2[i] || 0;
|
||||||
|
const percent = (count / 1000 * 100).toFixed(1);
|
||||||
|
const expected = [10, 7, 10, 2, 5, 8, 2, 11, 8, 7][i];
|
||||||
|
const expectedPercent = (expected / 70 * 100).toFixed(1);
|
||||||
|
console.log(` ${i}: ${count}次 (${percent}%) [期望: ${expectedPercent}%]`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n位置3(十位)频率:');
|
||||||
|
for (let i = 0; i <= 9; i++) {
|
||||||
|
const count = pos3[i] || 0;
|
||||||
|
const percent = (count / 1000 * 100).toFixed(1);
|
||||||
|
const expected = [10, 2, 4, 11, 8, 9, 6, 6, 7, 7][i];
|
||||||
|
const expectedPercent = (expected / 70 * 100).toFixed(1);
|
||||||
|
console.log(` ${i}: ${count}次 (${percent}%) [期望: ${expectedPercent}%]`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n=== 前20张生成的卡号 ===\n');
|
||||||
|
cards.slice(0, 20).forEach((card, i) => {
|
||||||
|
const last4 = card.number.slice(-4);
|
||||||
|
console.log(`${i + 1}. ${card.number} (后4位: ${last4})`);
|
||||||
|
});
|
||||||
|
|
||||||
|
const uniqueNumbers = new Set(cards.map(c => c.number));
|
||||||
|
console.log(`\n=== 去重检查 ===`);
|
||||||
|
console.log(`生成: 1000张`);
|
||||||
|
console.log(`唯一: ${uniqueNumbers.size}张`);
|
||||||
|
console.log(`重复: ${1000 - uniqueNumbers.size}张`);
|
||||||
|
}
|
||||||
|
|
||||||
|
test().catch(err => {
|
||||||
|
console.error('错误:', err.message);
|
||||||
|
console.error(err.stack);
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue
Block a user