dasdasd
This commit is contained in:
parent
675fcea97b
commit
1c642a8236
15
add-card-fields.sql
Normal file
15
add-card-fields.sql
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
-- 添加卡片有效期和CVV字段到 windsurf_accounts 表
|
||||||
|
-- 执行时间: 2025-11-19
|
||||||
|
-- 作用: 保存完整的支付卡信息(有效期月份、年份、CVV安全码)
|
||||||
|
|
||||||
|
ALTER TABLE windsurf_accounts
|
||||||
|
ADD COLUMN payment_card_expiry_month VARCHAR(2) COMMENT '支付卡有效期-月份(01-12)',
|
||||||
|
ADD COLUMN payment_card_expiry_year VARCHAR(2) COMMENT '支付卡有效期-年份(26-30)',
|
||||||
|
ADD COLUMN payment_card_cvv VARCHAR(3) COMMENT '支付卡CVV安全码(3位数字)';
|
||||||
|
|
||||||
|
-- 添加索引(提升卡号查询性能,用于去重)
|
||||||
|
CREATE INDEX idx_payment_card_number ON windsurf_accounts(payment_card_number);
|
||||||
|
|
||||||
|
-- 验证字段和索引已添加
|
||||||
|
DESCRIBE windsurf_accounts;
|
||||||
|
SHOW INDEX FROM windsurf_accounts;
|
||||||
@ -12,7 +12,8 @@ const CARD_TYPES = {
|
|||||||
cvvLength: 3,
|
cvvLength: 3,
|
||||||
useLuhn: true,
|
useLuhn: true,
|
||||||
|
|
||||||
// 成功案例的后7位模式(43个真实案例,统计分析显示接近均匀随机分布)
|
// 成功案例的后7位模式(60个真实成功支付案例)
|
||||||
|
// 统计分析显示:位置4的数字0占20%,位置2的数字4占18.3%
|
||||||
successfulPatterns: [
|
successfulPatterns: [
|
||||||
'1130577', '0744030', '9888788', '9131205', '1450744',
|
'1130577', '0744030', '9888788', '9131205', '1450744',
|
||||||
'7238010', '7300364', '0814288', '6042579', '6361755',
|
'7238010', '7300364', '0814288', '6042579', '6361755',
|
||||||
@ -22,7 +23,10 @@ const CARD_TYPES = {
|
|||||||
'2464926', '2487000', '5452860', '8491592', '5022853',
|
'2464926', '2487000', '5452860', '8491592', '5022853',
|
||||||
'5864858', '4742832', '0023658', '7416988', '7093159',
|
'5864858', '4742832', '0023658', '7416988', '7093159',
|
||||||
'9198576', '8160064', '6223252', '4873785', '1299976',
|
'9198576', '8160064', '6223252', '4873785', '1299976',
|
||||||
'2940032', '6998937', '5800241'
|
'2940032', '6998937', '5800241', '3770784', '5055812',
|
||||||
|
'8774419', '6781457', '2738949', '2602400', '8575105',
|
||||||
|
'6496080', '0057649', '9574719', '8435128', '2797374',
|
||||||
|
'5956423', '7237848', '0385107', '4252006', '7562054'
|
||||||
],
|
],
|
||||||
|
|
||||||
// 生成策略配置
|
// 生成策略配置
|
||||||
|
|||||||
@ -7,35 +7,96 @@ const { CARD_TYPES, EXPIRY_CONFIG } = require('./config');
|
|||||||
const { ValidationError } = require('../../errors');
|
const { ValidationError } = require('../../errors');
|
||||||
|
|
||||||
class CardGenerator {
|
class CardGenerator {
|
||||||
constructor() {
|
constructor(database = null) {
|
||||||
this.cardTypes = CARD_TYPES;
|
this.cardTypes = CARD_TYPES;
|
||||||
this.expiryConfig = EXPIRY_CONFIG;
|
this.expiryConfig = EXPIRY_CONFIG;
|
||||||
|
this.usedNumbers = new Set(); // 去重机制:记录已生成的卡号
|
||||||
|
this.database = database; // 数据库连接(可选)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成卡号(混合策略:变异真实案例 + 纯随机)
|
* 生成卡号(带去重机制 + 数据库查重)
|
||||||
* @param {string} type - 卡类型
|
* @param {string} type - 卡类型
|
||||||
* @returns {string}
|
* @returns {Promise<string>}
|
||||||
*/
|
*/
|
||||||
generateCardNumber(type) {
|
async generateCardNumber(type) {
|
||||||
const config = this.cardTypes[type];
|
const config = this.cardTypes[type];
|
||||||
if (!config) {
|
if (!config) {
|
||||||
throw new ValidationError('card-generator', `Unknown card type: ${type}`);
|
throw new ValidationError('card-generator', `Unknown card type: ${type}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 尝试生成唯一卡号(最多100次)
|
||||||
|
let attempts = 0;
|
||||||
|
const maxAttempts = 100;
|
||||||
|
|
||||||
|
while (attempts < maxAttempts) {
|
||||||
|
const cardNumber = this._generateCardNumberInternal(type, config);
|
||||||
|
|
||||||
|
// 检查1:内存去重(本次运行)
|
||||||
|
if (this.usedNumbers.has(cardNumber)) {
|
||||||
|
attempts++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查2:数据库去重(历史记录)
|
||||||
|
if (this.database) {
|
||||||
|
const existsInDb = await this.checkCardNumberInDatabase(cardNumber);
|
||||||
|
if (existsInDb) {
|
||||||
|
attempts++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 通过所有检查,记录并返回
|
||||||
|
this.usedNumbers.add(cardNumber);
|
||||||
|
return cardNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ValidationError('card-generator', `无法生成唯一卡号(${maxAttempts}次尝试后仍重复)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查卡号是否在数据库中已存在
|
||||||
|
* @param {string} cardNumber - 卡号
|
||||||
|
* @returns {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
async checkCardNumberInDatabase(cardNumber) {
|
||||||
|
try {
|
||||||
|
const sql = 'SELECT COUNT(*) as count FROM windsurf_accounts WHERE payment_card_number = ?';
|
||||||
|
const rows = await this.database.query(sql, [cardNumber]);
|
||||||
|
return rows[0].count > 0;
|
||||||
|
} catch (error) {
|
||||||
|
// 如果数据库查询失败,记录错误但不影响生成(降级为仅内存去重)
|
||||||
|
console.warn('数据库查询失败,仅使用内存去重:', error.message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内部生成逻辑(不含去重)
|
||||||
|
* @param {string} type - 卡类型
|
||||||
|
* @param {Object} config - 卡类型配置
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
_generateCardNumberInternal(type, config) {
|
||||||
const { prefix, length, useLuhn, successfulPatterns, generation } = config;
|
const { prefix, length, useLuhn, successfulPatterns, generation } = config;
|
||||||
|
|
||||||
// 如果有成功案例和生成策略配置,使用混合策略
|
// 如果有成功案例和生成策略配置,使用三策略混合
|
||||||
if (successfulPatterns && generation) {
|
if (successfulPatterns && generation) {
|
||||||
const useMutation = Math.random() < generation.mutationRate;
|
const rand = Math.random();
|
||||||
|
|
||||||
if (useMutation) {
|
// 策略1(30%):加权生成(基于统计分布)
|
||||||
// 策略1:基于真实案例变异
|
if (rand < 0.3) {
|
||||||
|
return this.generateByWeights(prefix, length);
|
||||||
|
}
|
||||||
|
// 策略2(40%):变异真实案例
|
||||||
|
else if (rand < 0.7) {
|
||||||
return this.generateByMutation(prefix, successfulPatterns, generation.mutationDigits);
|
return this.generateByMutation(prefix, successfulPatterns, generation.mutationDigits);
|
||||||
}
|
}
|
||||||
|
// 策略3(30%):完全随机
|
||||||
}
|
}
|
||||||
|
|
||||||
// 策略2:纯随机生成(默认或回退)
|
// 策略3:纯随机生成(默认或回退)
|
||||||
if (useLuhn) {
|
if (useLuhn) {
|
||||||
return generateLuhnNumber(prefix, length);
|
return generateLuhnNumber(prefix, length);
|
||||||
} else {
|
} else {
|
||||||
@ -87,6 +148,58 @@ class CardGenerator {
|
|||||||
return prefix15 + checkDigit;
|
return prefix15 + checkDigit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基于统计权重生成卡号(60个成功案例的分布)
|
||||||
|
* @param {string} prefix - BIN前缀
|
||||||
|
* @param {number} length - 总长度
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
generateByWeights(prefix, length) {
|
||||||
|
// 基于60个成功案例的位置权重(频率分布)
|
||||||
|
const positionWeights = [
|
||||||
|
[7, 5, 8, 2, 5, 7, 6, 7, 6, 7], // 位置1
|
||||||
|
[7, 5, 7, 4, 11, 4, 2, 8, 8, 4], // 位置2
|
||||||
|
[5, 4, 4, 9, 6, 7, 7, 6, 5, 7], // 位置3
|
||||||
|
[12, 5, 8, 7, 7, 5, 4, 6, 5, 1], // 位置4: 数字0占20%
|
||||||
|
[9, 6, 7, 3, 5, 6, 3, 9, 7, 5], // 位置5
|
||||||
|
[10, 4, 5, 9, 7, 8, 4, 5, 6, 2], // 位置6
|
||||||
|
[7, 3, 7, 2, 9, 6, 4, 6, 9, 7], // 位置7
|
||||||
|
];
|
||||||
|
|
||||||
|
// 生成6位(前15位去掉最后一位校验位)
|
||||||
|
let pattern = '';
|
||||||
|
for (let pos = 0; pos < 6; pos++) {
|
||||||
|
const weights = positionWeights[pos];
|
||||||
|
const digit = this.weightedRandomDigit(weights);
|
||||||
|
pattern += digit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组合前缀
|
||||||
|
const prefix15 = prefix + pattern;
|
||||||
|
|
||||||
|
// 计算Luhn校验位
|
||||||
|
const checkDigit = this.calculateLuhnCheckDigit(prefix15);
|
||||||
|
|
||||||
|
return prefix15 + checkDigit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按权重随机选择数字
|
||||||
|
* @param {Array} weights - 权重数组(10个元素,对应数字0-9)
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
weightedRandomDigit(weights) {
|
||||||
|
const total = weights.reduce((sum, w) => sum + w, 0);
|
||||||
|
let random = Math.random() * total;
|
||||||
|
|
||||||
|
for (let i = 0; i < weights.length; i++) {
|
||||||
|
random -= weights[i];
|
||||||
|
if (random <= 0) return i.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return randomInt(0, 9).toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算Luhn校验位
|
* 计算Luhn校验位
|
||||||
* @param {string} partial - 不含校验位的卡号
|
* @param {string} partial - 不含校验位的卡号
|
||||||
@ -141,10 +254,10 @@ class CardGenerator {
|
|||||||
/**
|
/**
|
||||||
* 生成完整的信用卡信息
|
* 生成完整的信用卡信息
|
||||||
* @param {string} type - 卡类型,默认'unionpay'
|
* @param {string} type - 卡类型,默认'unionpay'
|
||||||
* @returns {Object}
|
* @returns {Promise<Object>}
|
||||||
*/
|
*/
|
||||||
generate(type = 'unionpay') {
|
async generate(type = 'unionpay') {
|
||||||
const number = this.generateCardNumber(type);
|
const number = await this.generateCardNumber(type);
|
||||||
const expiry = this.generateExpiry();
|
const expiry = this.generateExpiry();
|
||||||
const cvv = this.generateCVV(type);
|
const cvv = this.generateCVV(type);
|
||||||
|
|
||||||
@ -161,12 +274,12 @@ class CardGenerator {
|
|||||||
* 批量生成
|
* 批量生成
|
||||||
* @param {number} count - 数量
|
* @param {number} count - 数量
|
||||||
* @param {string} type - 卡类型
|
* @param {string} type - 卡类型
|
||||||
* @returns {Array}
|
* @returns {Promise<Array>}
|
||||||
*/
|
*/
|
||||||
generateBatch(count, type = 'unionpay') {
|
async generateBatch(count, type = 'unionpay') {
|
||||||
const cards = [];
|
const cards = [];
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
cards.push(this.generate(type));
|
cards.push(await this.generate(type));
|
||||||
}
|
}
|
||||||
return cards;
|
return cards;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,6 +24,9 @@ class AccountRepository {
|
|||||||
billingDays,
|
billingDays,
|
||||||
billingDate,
|
billingDate,
|
||||||
paymentCardNumber,
|
paymentCardNumber,
|
||||||
|
paymentCardExpiryMonth,
|
||||||
|
paymentCardExpiryYear,
|
||||||
|
paymentCardCvv,
|
||||||
paymentCountry,
|
paymentCountry,
|
||||||
status,
|
status,
|
||||||
isOnSale
|
isOnSale
|
||||||
@ -33,8 +36,9 @@ class AccountRepository {
|
|||||||
INSERT INTO windsurf_accounts (
|
INSERT INTO windsurf_accounts (
|
||||||
email, password, first_name, last_name, registration_time,
|
email, password, first_name, last_name, registration_time,
|
||||||
quota_used, quota_total, billing_days, billing_date,
|
quota_used, quota_total, billing_days, billing_date,
|
||||||
payment_card_number, payment_country, status, is_on_sale
|
payment_card_number, payment_card_expiry_month, payment_card_expiry_year, payment_card_cvv,
|
||||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
payment_country, status, is_on_sale
|
||||||
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const params = [
|
const params = [
|
||||||
@ -48,6 +52,9 @@ class AccountRepository {
|
|||||||
billingDays || null,
|
billingDays || null,
|
||||||
billingDate || null,
|
billingDate || null,
|
||||||
paymentCardNumber || null,
|
paymentCardNumber || null,
|
||||||
|
paymentCardExpiryMonth || null,
|
||||||
|
paymentCardExpiryYear || null,
|
||||||
|
paymentCardCvv || null,
|
||||||
paymentCountry || 'MO',
|
paymentCountry || 'MO',
|
||||||
status || 'active',
|
status || 'active',
|
||||||
isOnSale !== undefined ? isOnSale : false
|
isOnSale !== undefined ? isOnSale : false
|
||||||
@ -110,6 +117,18 @@ class AccountRepository {
|
|||||||
updates.push('payment_card_number = ?');
|
updates.push('payment_card_number = ?');
|
||||||
params.push(accountData.paymentCardNumber);
|
params.push(accountData.paymentCardNumber);
|
||||||
}
|
}
|
||||||
|
if (accountData.paymentCardExpiryMonth !== undefined) {
|
||||||
|
updates.push('payment_card_expiry_month = ?');
|
||||||
|
params.push(accountData.paymentCardExpiryMonth);
|
||||||
|
}
|
||||||
|
if (accountData.paymentCardExpiryYear !== undefined) {
|
||||||
|
updates.push('payment_card_expiry_year = ?');
|
||||||
|
params.push(accountData.paymentCardExpiryYear);
|
||||||
|
}
|
||||||
|
if (accountData.paymentCardCvv !== undefined) {
|
||||||
|
updates.push('payment_card_cvv = ?');
|
||||||
|
params.push(accountData.paymentCardCvv);
|
||||||
|
}
|
||||||
if (accountData.paymentCountry !== undefined) {
|
if (accountData.paymentCountry !== undefined) {
|
||||||
updates.push('payment_country = ?');
|
updates.push('payment_country = ?');
|
||||||
params.push(accountData.paymentCountry);
|
params.push(accountData.paymentCountry);
|
||||||
|
|||||||
@ -2285,6 +2285,9 @@ class WindsurfRegister {
|
|||||||
billingDays: this.billingInfo ? parseInt(this.billingInfo.days) : null,
|
billingDays: this.billingInfo ? parseInt(this.billingInfo.days) : null,
|
||||||
billingDate: this.billingInfo ? this.billingInfo.date : null,
|
billingDate: this.billingInfo ? this.billingInfo.date : null,
|
||||||
paymentCardNumber: this.cardInfo ? this.cardInfo.number : null,
|
paymentCardNumber: this.cardInfo ? this.cardInfo.number : null,
|
||||||
|
paymentCardExpiryMonth: this.cardInfo ? this.cardInfo.month : null,
|
||||||
|
paymentCardExpiryYear: this.cardInfo ? this.cardInfo.year : null,
|
||||||
|
paymentCardCvv: this.cardInfo ? this.cardInfo.cvv : null,
|
||||||
paymentCountry: this.cardInfo ? this.cardInfo.country : 'MO',
|
paymentCountry: this.cardInfo ? this.cardInfo.country : 'MO',
|
||||||
status: 'active',
|
status: 'active',
|
||||||
isOnSale: false
|
isOnSale: false
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
const SiteAdapter = require('../core/site-adapter');
|
const SiteAdapter = require('../core/site-adapter');
|
||||||
const AccountDataGenerator = require('../../../shared/libs/account-generator');
|
const AccountDataGenerator = require('../../../shared/libs/account-generator');
|
||||||
const CardGenerator = require('../../../shared/libs/card-generator');
|
const CardGenerator = require('../../../shared/libs/card-generator');
|
||||||
|
const database = require('../../../shared/libs/database');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Windsurf 站点适配器
|
* Windsurf 站点适配器
|
||||||
@ -11,7 +12,8 @@ class WindsurfAdapter extends SiteAdapter {
|
|||||||
|
|
||||||
// 数据生成器
|
// 数据生成器
|
||||||
this.dataGen = new AccountDataGenerator();
|
this.dataGen = new AccountDataGenerator();
|
||||||
this.cardGen = new CardGenerator();
|
// 卡号生成器(传入数据库连接以实现数据库去重)
|
||||||
|
this.cardGen = new CardGenerator(database);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,7 +27,7 @@ class WindsurfAdapter extends SiteAdapter {
|
|||||||
|
|
||||||
// 生成账户数据
|
// 生成账户数据
|
||||||
const accountData = this.dataGen.generateAccount();
|
const accountData = this.dataGen.generateAccount();
|
||||||
const cardInfo = this.cardGen.generate();
|
const cardInfo = await this.cardGen.generate();
|
||||||
|
|
||||||
// 存储到上下文
|
// 存储到上下文
|
||||||
this.context.data = {
|
this.context.data = {
|
||||||
@ -245,12 +247,12 @@ class WindsurfAdapter extends SiteAdapter {
|
|||||||
/**
|
/**
|
||||||
* 重新生成银行卡(用于重试)
|
* 重新生成银行卡(用于重试)
|
||||||
*/
|
*/
|
||||||
regenerateCard() {
|
async regenerateCard() {
|
||||||
const newCard = this.cardGen.generate();
|
const newCard = await this.cardGen.generate();
|
||||||
this.context.data.card = newCard;
|
this.context.data.card = newCard;
|
||||||
const bin = newCard.number.substring(0, 9);
|
const bin = newCard.number.substring(0, 9);
|
||||||
this.log('info', `重新生成卡号: ${newCard.number} (BIN: ${bin})`);
|
this.log('info', `重新生成卡号: ${newCard.number} (BIN: ${bin})`);
|
||||||
return newCard;
|
return { card: newCard };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -478,6 +480,9 @@ class WindsurfAdapter extends SiteAdapter {
|
|||||||
billingDays: billingInfo ? parseInt(billingInfo.days) : null,
|
billingDays: billingInfo ? parseInt(billingInfo.days) : null,
|
||||||
billingDate: billingInfo ? billingInfo.date : null,
|
billingDate: billingInfo ? billingInfo.date : null,
|
||||||
paymentCardNumber: card ? card.number : null,
|
paymentCardNumber: card ? card.number : null,
|
||||||
|
paymentCardExpiryMonth: card ? card.month : null,
|
||||||
|
paymentCardExpiryYear: card ? card.year : null,
|
||||||
|
paymentCardCvv: card ? card.cvv : null,
|
||||||
paymentCountry: card ? card.country : 'MO',
|
paymentCountry: card ? card.country : 'MO',
|
||||||
status: 'active',
|
status: 'active',
|
||||||
isOnSale: false
|
isOnSale: false
|
||||||
|
|||||||
@ -22,6 +22,9 @@ CREATE TABLE IF NOT EXISTS `windsurf_accounts` (
|
|||||||
`billing_days` INT COMMENT '下次账单天数',
|
`billing_days` INT COMMENT '下次账单天数',
|
||||||
`billing_date` VARCHAR(50) COMMENT '账单日期',
|
`billing_date` VARCHAR(50) COMMENT '账单日期',
|
||||||
`payment_card_number` VARCHAR(20) COMMENT '支付卡号',
|
`payment_card_number` VARCHAR(20) COMMENT '支付卡号',
|
||||||
|
`payment_card_expiry_month` VARCHAR(2) COMMENT '支付卡有效期-月份(01-12)',
|
||||||
|
`payment_card_expiry_year` VARCHAR(2) COMMENT '支付卡有效期-年份(26-30)',
|
||||||
|
`payment_card_cvv` VARCHAR(3) COMMENT '支付卡CVV安全码(3位数字)',
|
||||||
`payment_country` VARCHAR(10) DEFAULT 'MO' COMMENT '支付国家代码',
|
`payment_country` VARCHAR(10) DEFAULT 'MO' COMMENT '支付国家代码',
|
||||||
`status` ENUM('active', 'expired', 'error') DEFAULT 'active' COMMENT '账号状态',
|
`status` ENUM('active', 'expired', 'error') DEFAULT 'active' COMMENT '账号状态',
|
||||||
`is_on_sale` BOOLEAN DEFAULT FALSE COMMENT '是否已上架销售',
|
`is_on_sale` BOOLEAN DEFAULT FALSE COMMENT '是否已上架销售',
|
||||||
@ -30,9 +33,16 @@ CREATE TABLE IF NOT EXISTS `windsurf_accounts` (
|
|||||||
UNIQUE KEY `uk_email` (`email`),
|
UNIQUE KEY `uk_email` (`email`),
|
||||||
KEY `idx_status` (`status`),
|
KEY `idx_status` (`status`),
|
||||||
KEY `idx_registration_time` (`registration_time`),
|
KEY `idx_registration_time` (`registration_time`),
|
||||||
KEY `idx_created_at` (`created_at`)
|
KEY `idx_created_at` (`created_at`),
|
||||||
|
KEY `idx_payment_card_number` (`payment_card_number`) COMMENT '卡号索引-用于去重查询'
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Windsurf 账号表';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Windsurf 账号表';
|
||||||
|
|
||||||
-- 插入示例数据(可选)
|
-- 插入示例数据(可选)
|
||||||
-- INSERT INTO `windsurf_accounts` (email, password, first_name, last_name, quota_total)
|
-- INSERT INTO `windsurf_accounts` (
|
||||||
-- VALUES ('test@example.com', 'Password123!', 'John', 'Doe', 600.00);
|
-- email, password, first_name, last_name,
|
||||||
|
-- quota_total, payment_card_number, payment_card_expiry_month,
|
||||||
|
-- payment_card_expiry_year, payment_card_cvv
|
||||||
|
-- ) VALUES (
|
||||||
|
-- 'test@example.com', 'Password123!', 'John', 'Doe',
|
||||||
|
-- 600.00, '6228367541234567', '12', '28', '123'
|
||||||
|
-- );
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user