初始化提交:go比特版本精简
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'recharge-db-'));
|
||||
const Config = require('../src/core/config');
|
||||
Config.DATA_DIR = tempDir;
|
||||
Config.DB_PATH = path.join(tempDir, 'accounts.db');
|
||||
const database = require('../src/core/database');
|
||||
|
||||
try {
|
||||
database.initDB();
|
||||
const columns = database.getDb().pragma('table_info(accounts)').map(row => row.name);
|
||||
for (const column of [
|
||||
'recharge_status', 'recharge_task_id', 'recharge_message', 'recharged_at', 'recharge_operation_id',
|
||||
'recharge_card_key',
|
||||
]) {
|
||||
assert(columns.includes(column), `账号表应包含 ${column}`);
|
||||
}
|
||||
const attemptColumns = database.getDb().pragma('table_info(recharge_attempts)').map(row => row.name);
|
||||
for (const column of ['operation_id', 'email', 'attempt_no', 'remote_task_id', 'status']) {
|
||||
assert(attemptColumns.includes(column), `充值尝试表应包含 ${column}`);
|
||||
}
|
||||
|
||||
const email = 'recharge@example.com';
|
||||
database.upsertAccount({ email, password: 'secret' });
|
||||
|
||||
assert.strictEqual(database.updateAccountRecharge(email, '充值中', 123, null), true);
|
||||
let account = database.getAccount(email);
|
||||
assert.strictEqual(account.recharge_status, '充值中');
|
||||
assert.strictEqual(account.recharge_task_id, '123');
|
||||
assert.strictEqual(account.recharge_message, null);
|
||||
assert.strictEqual(account.message, null);
|
||||
assert.strictEqual(account.recharged_at, null);
|
||||
|
||||
assert.strictEqual(database.updateAccountRecharge(email, '充值失败', 123, 'remote_error'), true);
|
||||
account = database.getAccount(email);
|
||||
assert.strictEqual(account.recharge_status, '充值失败');
|
||||
assert.strictEqual(account.recharge_message, 'remote_error');
|
||||
assert.strictEqual(account.message, 'remote_error', '充值结论应同步到通用处理结论');
|
||||
assert.ok(account.recharged_at, '充值失败也应记录本次自动处理完成时间');
|
||||
|
||||
assert.strictEqual(database.updateAccountRecharge(email, '充值成功', 123, 'success'), true);
|
||||
account = database.getAccount(email);
|
||||
assert.strictEqual(account.recharge_status, '充值成功');
|
||||
assert.strictEqual(account.recharge_task_id, '123');
|
||||
assert.strictEqual(account.recharge_message, 'success');
|
||||
assert.strictEqual(account.message, 'success', '充值成功后处理结论不应停在等待充值');
|
||||
assert.ok(account.recharged_at, '充值成功应记录完成时间');
|
||||
|
||||
assert.strictEqual(database.updateAccountRecharge('missing@example.com', '充值成功'), false);
|
||||
|
||||
const firstOperation = `cardpay-v1-${'a'.repeat(64)}`;
|
||||
const otherOperation = `cardpay-v1-${'b'.repeat(64)}`;
|
||||
assert.deepStrictEqual(
|
||||
database.claimAccountsForRecharge([{ email, operationId: firstOperation, cardKey: 'CARD-FIRST' }]),
|
||||
{ success: true },
|
||||
);
|
||||
account = database.getAccount(email);
|
||||
assert.strictEqual(account.recharge_status, '充值中');
|
||||
assert.strictEqual(account.recharge_operation_id, firstOperation);
|
||||
assert.strictEqual(account.recharge_task_id, null, '新操作占用时应清除上一任务编号');
|
||||
assert.strictEqual(account.recharge_card_key, 'CARD-FIRST', '应保存本次实际使用的卡密');
|
||||
assert.strictEqual(account.message, '等待充值', '进入充值队列时处理结论应显示等待充值');
|
||||
|
||||
database.updateAccountRecharge(email, '充值中', 456, '结果待确认');
|
||||
assert.deepStrictEqual(
|
||||
database.claimAccountsForRecharge([{ email, operationId: firstOperation, cardKey: 'CARD-FIRST' }]),
|
||||
{ success: true },
|
||||
'相同操作必须允许幂等恢复',
|
||||
);
|
||||
assert.strictEqual(database.getAccount(email).recharge_task_id, '456', '幂等恢复必须保留任务编号');
|
||||
assert.deepStrictEqual(
|
||||
database.claimAccountsForRecharge([{ email, operationId: otherOperation, cardKey: 'CARD-OTHER' }]),
|
||||
{ success: false, code: 'RECHARGE_ACCOUNT_BUSY' },
|
||||
'未知结果时必须拒绝换卡并行充值',
|
||||
);
|
||||
|
||||
database.updateAccountRecharge(email, '等待已确认', 456, '等待人工确认');
|
||||
assert.ok(database.getAccount(email).recharged_at, '等待人工确认应记录自动处理结束时间');
|
||||
assert.deepStrictEqual(
|
||||
database.claimAccountsForRecharge([{ email, operationId: otherOperation, cardKey: 'CARD-OTHER' }]),
|
||||
{ success: true },
|
||||
'等待人工确认不是锁定状态,应允许人工决定后再次充值',
|
||||
);
|
||||
account = database.getAccount(email);
|
||||
assert.strictEqual(account.recharge_status, '充值中');
|
||||
assert.strictEqual(account.recharge_operation_id, otherOperation);
|
||||
assert.strictEqual(account.recharge_task_id, null, '再次充值应开始新的操作并清除旧任务编号');
|
||||
assert.strictEqual(account.recharge_card_key, 'CARD-OTHER', '再次充值应覆盖为本次使用的卡密');
|
||||
assert.strictEqual(account.recharged_at, null, '再次充值开始时应清空上一次完成时间');
|
||||
|
||||
const failedEmail = 'recharge-failed@example.com';
|
||||
database.upsertAccount({ email: failedEmail, password: 'secret' });
|
||||
assert.deepStrictEqual(
|
||||
database.claimAccountsForRecharge([{
|
||||
email: failedEmail,
|
||||
operationId: firstOperation,
|
||||
cardKey: 'FAILED-CARD-FIRST',
|
||||
}]),
|
||||
{ success: true },
|
||||
);
|
||||
database.updateAccountRecharge(failedEmail, '充值失败', null, '第一次充值失败');
|
||||
assert.deepStrictEqual(
|
||||
database.claimAccountsForRecharge([{
|
||||
email: failedEmail,
|
||||
operationId: otherOperation,
|
||||
cardKey: 'FAILED-CARD-RETRY',
|
||||
}]),
|
||||
{ success: true },
|
||||
'充值失败状态必须允许换卡再次充值',
|
||||
);
|
||||
assert.strictEqual(
|
||||
database.getAccount(failedEmail).recharge_card_key,
|
||||
'FAILED-CARD-RETRY',
|
||||
'失败后再次充值应记录新一轮使用的卡密',
|
||||
);
|
||||
|
||||
const guardedEmail = 'recharge-guarded@example.com';
|
||||
database.upsertAccount({ email: guardedEmail, password: 'secret' });
|
||||
assert.deepStrictEqual(database.claimAccountsForRecharge([{
|
||||
email: guardedEmail,
|
||||
operationId: firstOperation,
|
||||
cardKey: 'GUARDED-CARD',
|
||||
}]), { success: true });
|
||||
assert.strictEqual(
|
||||
database.recordRechargeAttempt(guardedEmail, firstOperation, 1, '701', 'pending', 'pending'),
|
||||
true,
|
||||
);
|
||||
assert.strictEqual(
|
||||
database.recordRechargeAttempt(guardedEmail, firstOperation, 2, '702', 'failed', 'failed'),
|
||||
true,
|
||||
);
|
||||
assert.strictEqual(
|
||||
database.recordRechargeAttempt(guardedEmail, firstOperation, 3, '703', 'success', 'success'),
|
||||
true,
|
||||
);
|
||||
assert.deepStrictEqual(
|
||||
database.getRechargeAttempts(guardedEmail, firstOperation).map(row => [row.attempt_no, row.remote_task_id, row.status]),
|
||||
[[1, '701', 'pending'], [2, '702', 'failed'], [3, '703', 'success']],
|
||||
'同一次充值产生的全部远端任务号都必须保留',
|
||||
);
|
||||
assert.strictEqual(
|
||||
database.updateAccountRechargeForOperation(guardedEmail, firstOperation, '充值成功', '703', 'success'),
|
||||
true,
|
||||
);
|
||||
assert.strictEqual(
|
||||
database.updateAccountRechargeForOperation(guardedEmail, firstOperation, '充值失败', '702', 'late failure'),
|
||||
true,
|
||||
'晚到失败消息应被安全忽略',
|
||||
);
|
||||
assert.strictEqual(database.getAccount(guardedEmail).recharge_status, '充值成功',
|
||||
'同一操作一旦成功不得被晚到失败状态降级');
|
||||
assert.strictEqual(
|
||||
database.updateAccountRechargeForOperation(guardedEmail, otherOperation, '充值失败', '999', 'stale'),
|
||||
false,
|
||||
'旧操作或伪造操作号不得覆盖当前充值状态',
|
||||
);
|
||||
console.log('recharge_database.test.js: PASS');
|
||||
} finally {
|
||||
try { database.getDb().close(); } catch (_) {}
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
Reference in New Issue
Block a user