初始化提交:go比特版本精简

This commit is contained in:
2026-09-20 17:02:11 +08:00
commit f41a979462
213 changed files with 58288 additions and 0 deletions
+416
View File
@@ -0,0 +1,416 @@
'use strict';
const assert = require('assert');
const {
executeCardPayRecharge,
executeCardPayRechargeWithRetry,
pollCardPayTask,
parseRechargeSession,
safeRechargeFailure,
shouldRetryRechargeFailure,
rechargeNeedsManualConfirmation,
createRechargeOperationId,
} = require('../src/services/recharge_task_service');
function jwt(payload) {
const encode = value => Buffer.from(JSON.stringify(value)).toString('base64url');
return `${encode({ alg: 'none' })}.${encode(payload)}.`;
}
function session(email = 'target@gmail.com') {
return JSON.stringify({
user: { email },
expires: '2099-01-01T00:00:00.000Z',
accessToken: jwt({ exp: 4070908800 }),
sessionToken: 'must-not-be-used',
});
}
(async () => {
const parsed = parseRechargeSession(session('Target@Gmail.com'), 'target@gmail.com', { nowMs: 1 });
assert(parsed.session.accessToken.includes('.'));
assert.strictEqual(parsed.session.sessionToken, 'must-not-be-used');
assert.strictEqual(parsed.session.user.email, 'Target@Gmail.com');
assert.deepStrictEqual(JSON.parse(parsed.loginContent), parsed.session);
const operationId = createRechargeOperationId('Target@Gmail.com', 'PRIVATE-CARD');
assert(operationId.startsWith('cardpay-v1-'));
assert.strictEqual(
operationId,
createRechargeOperationId('target@gmail.com', 'PRIVATE-CARD'),
'同一账号和卡密重试必须得到稳定幂等操作号',
);
assert.notStrictEqual(operationId, createRechargeOperationId('target@gmail.com', 'OTHER-CARD'));
assert.strictEqual(operationId.includes('PRIVATE-CARD'), false, '幂等操作号不得暴露卡密');
assert.throws(
() => parseRechargeSession(session('other@gmail.com'), 'target@gmail.com'),
error => error && error.code === 'RECHARGE_SESSION_ACCOUNT_MISMATCH',
);
assert.doesNotThrow(
() => parseRechargeSession(session('firstlast@gmail.com'), 'First.Last@gmail.com'),
'Gmail Session 返回无点号地址时应识别为同一充值账号',
);
assert.doesNotThrow(
() => parseRechargeSession(JSON.stringify({
user: { email: 'firstlast@gmail.com' },
expires: '2099-01-01T00:00:00.000Z',
accessToken: jwt({
exp: 4070908800,
'https://api.openai.com/profile': { email: 'firstlast@googlemail.com' },
}),
}), 'First.Last@gmail.com'),
'Session user 和 accessToken 都应按 Gmail 点号及大小写规则校验',
);
assert.throws(
() => parseRechargeSession(session('firstlast@example.com'), 'first.last@example.com'),
error => error && error.code === 'RECHARGE_SESSION_ACCOUNT_MISMATCH',
'非 Gmail 邮箱不得忽略用户名中的点',
);
assert.throws(
() => parseRechargeSession(session('first.last+tag@gmail.com'), 'first.last@gmail.com'),
error => error && error.code === 'RECHARGE_SESSION_ACCOUNT_MISMATCH',
'本次兼容仅忽略 Gmail 用户名中的点和大小写,不放宽 +tag 校验',
);
assert.throws(
() => parseRechargeSession(JSON.stringify({ user: { email: 'target@gmail.com' } }), 'target@gmail.com'),
error => error && error.code === 'RECHARGE_ACCESS_TOKEN_MISSING',
);
assert.throws(
() => parseRechargeSession(JSON.stringify({
user: { email: 'target@gmail.com' },
expires: '2099-01-01T00:00:00.000Z',
accessToken: jwt({
exp: 4070908800,
'https://api.openai.com/profile': { email: 'other@gmail.com' },
}),
}), 'target@gmail.com'),
error => error && error.code === 'RECHARGE_SESSION_ACCOUNT_MISMATCH',
);
assert.throws(
() => parseRechargeSession(JSON.stringify({
user: { email: 'target@gmail.com' },
expires: '2020-01-01T00:00:00.000Z',
accessToken: jwt({ exp: 4070908800 }),
}), 'target@gmail.com'),
error => error && error.code === 'RECHARGE_SESSION_EXPIRED',
);
const calls = [];
const client = {
async prepareCardPay(input) {
calls.push({ stage: 'prepare', input });
return { success: true, prepareToken: 'local-prepare', taskId: '41' };
},
async confirmCardPay(input) {
calls.push({ stage: 'confirm', input });
return { success: true, status: 'processing', taskId: '41' };
},
async getTask(input) {
calls.push({ stage: 'task', input });
return { success: true, status: 'success', taskId: '41', accountEmail: 'target@gmail.com' };
},
};
const result = await executeCardPayRecharge({
client,
email: 'target@gmail.com',
cardKey: 'unit-card-key',
sessionText: session('target@gmail.com'),
operationId: 'unit-operation-123456',
nowMs: 1,
now: () => 100,
pollIntervalMs: 10,
pollTimeoutMs: 100,
requestMaxAttempts: 1,
sleep: async () => {},
onPrepared: async info => calls.push({ stage: 'prepared_callback', input: info }),
onConfirmed: async info => calls.push({ stage: 'confirmed_callback', input: info }),
onPoll: async info => calls.push({ stage: 'poll_callback', input: info }),
});
assert.deepStrictEqual(result, { success: true, taskId: '41', status: 'success' });
assert.deepStrictEqual(calls.map(call => call.stage), [
'prepare', 'prepared_callback', 'confirm', 'confirmed_callback', 'task', 'poll_callback',
]);
const expectedSession = JSON.parse(session('target@gmail.com'));
assert.deepStrictEqual(JSON.parse(calls[0].input.loginContent), expectedSession);
assert.strictEqual(calls[2].input.loginContent, calls[0].input.loginContent);
assert.strictEqual(Object.prototype.hasOwnProperty.call(calls[0].input, 'accessToken'), false);
assert.strictEqual(Object.prototype.hasOwnProperty.call(calls[0].input, 'session'), false);
assert.strictEqual(JSON.parse(calls[0].input.loginContent).sessionToken, 'must-not-be-used');
assert.strictEqual(Object.prototype.hasOwnProperty.call(calls[2].input, 'cardKey'), false);
assert.notStrictEqual(calls[0].input.operationId, '');
assert.strictEqual(calls[0].input.maxAttempts, 1);
assert.strictEqual(calls[2].input.maxAttempts, 1);
let delayedClock = 0;
let delayedQueries = 0;
const delayedResult = await pollCardPayTask({
client: {
async getTask() {
delayedQueries += 1;
if (delayedQueries === 1) {
throw Object.assign(new Error('temporary'), {
code: 'GPTPAY_NETWORK_ERROR',
retryable: true,
});
}
if (delayedQueries === 2) return { success: true, taskId: '77', status: 'pending' };
return { success: true, taskId: '77', status: 'success' };
},
},
taskId: '77',
expectedEmail: 'target@gmail.com',
pollIntervalMs: 10,
pollTimeoutMs: 100,
now: () => delayedClock,
sleep: async delay => { delayedClock += delay; },
});
assert.deepStrictEqual(delayedResult, { success: true, taskId: '77', status: 'success' });
assert.strictEqual(delayedQueries, 3, '短时查询错误后必须继续核对同一个任务号');
let timeoutClock = 0;
const timeoutError = await pollCardPayTask({
client: {
async getTask() { return { success: true, taskId: '78', status: 'pending' }; },
},
taskId: '78',
expectedEmail: 'target@gmail.com',
pollIntervalMs: 10,
pollTimeoutMs: 30,
now: () => timeoutClock,
sleep: async delay => { timeoutClock += delay; },
}).then(() => null, error => error);
assert.strictEqual(timeoutError.code, 'RECHARGE_TASK_TIMEOUT');
assert.strictEqual(timeoutError.taskId, '78');
assert.strictEqual(shouldRetryRechargeFailure(timeoutError), false,
'已有任务号仍在处理中时不能重新预创建');
let manualClock = 0;
await assert.rejects(
pollCardPayTask({
client: {
async getTask() {
return { success: true, taskId: '79', status: 'manual_confirmation' };
},
},
taskId: '79',
expectedEmail: 'target@gmail.com',
pollIntervalMs: 10,
pollTimeoutMs: 30,
now: () => manualClock,
sleep: async delay => { manualClock += delay; },
}),
error => error && error.code === 'RECHARGE_RESULT_PENDING' && error.taskId === '79',
'主系统明确人工确认状态时才应停止自动查询',
);
let confirmRecoveryClock = 0;
let confirmRecoveryPrepareCalls = 0;
let confirmRecoveryQueries = 0;
const confirmRecoveryResult = await executeCardPayRechargeWithRetry({
client: {
async prepareCardPay() {
confirmRecoveryPrepareCalls += 1;
return { success: true, prepareToken: 'recover-token', taskId: '80' };
},
async confirmCardPay() {
throw Object.assign(new Error('confirm response lost'), {
code: 'GPTPAY_NETWORK_ERROR',
retryable: true,
});
},
async getTask() {
confirmRecoveryQueries += 1;
return confirmRecoveryQueries < 2
? { success: true, taskId: '80', status: 'pending' }
: { success: true, taskId: '80', status: 'success' };
},
},
email: 'target@gmail.com',
cardKey: 'RECOVER-SAME-CARD',
sessionText: session('target@gmail.com'),
operationId: 'confirm-recovery-operation',
nowMs: 1,
pollIntervalMs: 10,
pollTimeoutMs: 50,
now: () => confirmRecoveryClock,
sleep: async delay => { confirmRecoveryClock += delay; },
retrySleep: async () => {},
});
assert.deepStrictEqual(confirmRecoveryResult, { success: true, taskId: '80', status: 'success' });
assert.strictEqual(confirmRecoveryPrepareCalls, 1,
'确认响应异常但已有任务号时不得重新创建支付任务');
let terminalRetryClock = 0;
const terminalRetryOperationIds = [];
let terminalRetryTaskNo = 90;
const terminalRetryResult = await executeCardPayRechargeWithRetry({
client: {
async prepareCardPay(input) {
terminalRetryOperationIds.push(input.operationId);
terminalRetryTaskNo += 1;
return {
success: true,
prepareToken: `terminal-token-${terminalRetryTaskNo}`,
taskId: String(terminalRetryTaskNo),
};
},
async confirmCardPay(input) {
return { success: true, status: 'processing', taskId: String(input.expectedTaskId) };
},
async getTask(input) {
return input.taskId === '91'
? { success: true, taskId: '91', status: 'failed', failed: true }
: { success: true, taskId: '92', status: 'success', failed: false };
},
},
email: 'target@gmail.com',
cardKey: 'TERMINAL-RETRY-SAME-CARD',
sessionText: session('target@gmail.com'),
operationId: 'terminal-retry-operation',
nowMs: 1,
maxAttempts: 3,
pollIntervalMs: 10,
pollTimeoutMs: 100,
now: () => terminalRetryClock,
sleep: async delay => { terminalRetryClock += delay; },
retrySleep: async () => {},
});
assert.deepStrictEqual(terminalRetryResult, { success: true, taskId: '92', status: 'success' });
assert.deepStrictEqual(terminalRetryOperationIds, [
'terminal-retry-operation',
'terminal-retry-operation-retry-2',
], '只有远端任务明确失败后才能创建新的幂等尝试');
const retryPrepareCalls = [];
const retryEvents = [];
const retryDelays = [];
const retryClient = {
async prepareCardPay(input) {
retryPrepareCalls.push(input);
if (retryPrepareCalls.length < 3) {
throw Object.assign(new Error('private-card-lookup-detail'), {
code: 'GPTPAY_BUSINESS_REJECTED',
errorCode: 'card_not_found',
});
}
return { success: true, prepareToken: 'retry-prepare-token', taskId: '88' };
},
async confirmCardPay() {
return { success: true, status: 'success', taskId: '88' };
},
async getTask() { throw new Error('must not query an immediate success'); },
};
const retriedResult = await executeCardPayRechargeWithRetry({
client: retryClient,
email: 'target@gmail.com',
cardKey: 'SAME-CARD-FOR-ALL-ATTEMPTS',
sessionText: session('target@gmail.com'),
operationId: 'stable-operation-for-three-attempts',
nowMs: 1,
maxAttempts: 3,
retryDelayMs: 10,
retrySleep: async delay => retryDelays.push(delay),
onAttempt: async info => retryEvents.push({ stage: 'attempt', ...info }),
onRetry: async info => retryEvents.push({ stage: 'retry', ...info }),
});
assert.deepStrictEqual(retriedResult, { success: true, taskId: '88', status: 'success' });
assert.strictEqual(retryPrepareCalls.length, 3, '直接失败后最多应尝试三次');
assert.deepStrictEqual(
retryPrepareCalls.map(input => input.cardKey),
Array(3).fill('SAME-CARD-FOR-ALL-ATTEMPTS'),
'每次重试必须使用完全相同的卡密',
);
assert.deepStrictEqual(
retryPrepareCalls.map(input => input.operationId),
Array(3).fill('stable-operation-for-three-attempts'),
'每次重试必须复用同一个幂等操作号',
);
assert.deepStrictEqual(retryDelays, [10, 20]);
assert.deepStrictEqual(
retryEvents.filter(event => event.stage === 'attempt').map(event => event.attempt),
[1, 2, 3],
);
assert.strictEqual(
JSON.stringify(retryEvents).includes('private-card-lookup-detail'),
false,
'重试事件不得暴露上游原始错误内容',
);
const duplicateClient = {
async prepareCardPay() { return { success: false, requiresDuplicateConfirm: true }; },
async confirmCardPay() { throw new Error('must not confirm'); },
async getTask() { throw new Error('must not query'); },
};
await assert.rejects(
executeCardPayRecharge({
client: duplicateClient,
email: 'target@gmail.com',
cardKey: 'unit-card-key',
sessionText: session('target@gmail.com'),
operationId: 'unit-operation-duplicate',
nowMs: 1,
}),
error => error && error.code === 'RECHARGE_DUPLICATE_CONFIRM_REQUIRED',
);
const safe = safeRechargeFailure(Object.assign(new Error('secret-card-token'), {
code: 'GPTPAY_API_REJECTED',
}));
assert.deepStrictEqual(safe, {
code: 'GPTPAY_API_REJECTED',
message: '充值接口签名、权限或请求被拒绝',
});
assert.strictEqual(JSON.stringify(safe).includes('secret-card-token'), false);
const safeLineMismatch = safeRechargeFailure(Object.assign(new Error('private-upstream-message'), {
code: 'GPTPAY_BUSINESS_REJECTED',
errorCode: 'fulfillment_mode_mismatch',
requestId: 'safe-request-123',
}));
assert.deepStrictEqual(safeLineMismatch, {
code: 'GPTPAY_BUSINESS_REJECTED',
message: '卡密不是卡付线路,当前充值入口无法处理',
errorCode: 'fulfillment_mode_mismatch',
requestId: 'safe-request-123',
});
assert.strictEqual(JSON.stringify(safeLineMismatch).includes('private-upstream-message'), false);
assert.strictEqual(shouldRetryRechargeFailure(Object.assign(new Error('lookup'), {
code: 'GPTPAY_BUSINESS_REJECTED',
errorCode: 'card_not_found',
})), true, '卡密暂未查到时应使用同一卡密重试');
assert.strictEqual(shouldRetryRechargeFailure(Object.assign(new Error('line'), {
code: 'GPTPAY_BUSINESS_REJECTED',
errorCode: 'fulfillment_mode_mismatch',
})), false, '线路固定不匹配不应空转重试');
assert.strictEqual(shouldRetryRechargeFailure(Object.assign(new Error('failed'), {
code: 'RECHARGE_TASK_FAILED',
})), true, '主系统明确执行失败应进入同卡重试');
assert.strictEqual(shouldRetryRechargeFailure(Object.assign(new Error('session'), {
code: 'RECHARGE_SESSION_INVALID',
})), false, '本地 Session 无效不应调用外部接口重试');
assert.strictEqual(rechargeNeedsManualConfirmation(Object.assign(new Error('business'), {
code: 'GPTPAY_BUSINESS_REJECTED',
errorCode: 'card_not_found',
}), '501'), false, '已有远端任务号时应继续对账同一任务,不能伪装成人工待确认');
assert.strictEqual(rechargeNeedsManualConfirmation(Object.assign(new Error('manual'), {
code: 'RECHARGE_RESULT_PENDING',
taskId: '501',
}), '501'), true, '只有主系统明确结果待确认时才应等待人工确认');
assert.strictEqual(rechargeNeedsManualConfirmation(Object.assign(new Error('business'), {
code: 'GPTPAY_BUSINESS_REJECTED',
errorCode: 'card_not_found',
}), null), false, '预创建前明确拒绝且没有任务号时可显示失败');
assert.strictEqual(rechargeNeedsManualConfirmation(Object.assign(new Error('terminal'), {
code: 'RECHARGE_TASK_FAILED',
taskId: '502',
}), '502'), false, '远端任务明确终止失败时应显示充值失败');
assert.strictEqual(rechargeNeedsManualConfirmation(Object.assign(new Error('network'), {
code: 'GPTPAY_NETWORK_ERROR',
retryable: true,
}), null), true, '没有任务号但修改请求结果未知时也应等待人工确认');
console.log('recharge_task_service.test.js: PASS');
})().catch(error => {
console.error(error);
process.exitCode = 1;
});