fix(gpc): query local OTP helper by phone

This commit is contained in:
朴圣佑
2026-05-07 12:12:57 +08:00
parent 250a709f20
commit 2236730374
6 changed files with 227 additions and 38 deletions
+56
View File
@@ -79,3 +79,59 @@ print(json.dumps(payload))
none_after_fresh: true,
});
});
test('GPC SMS helper selects and consumes cached OTP records by phone', () => {
const code = `
import importlib.util
import json
script_path = ${JSON.stringify(scriptPath)}
spec = importlib.util.spec_from_file_location("gpc_sms_helper_macos", script_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
record_a = {
"otp": "111111",
"code": "111111",
"message_id": "a",
"rowid": 1,
"phone_e164": "+8615808505050",
"account_phone": "+8615808505050",
"received_at": "2026-05-05T00:00:00+00:00",
}
record_b = {
"otp": "222222",
"code": "222222",
"message_id": "b",
"rowid": 2,
"phone_e164": "+8618984829950",
"account_phone": "+8618984829950",
"received_at": "2026-05-05T00:00:10+00:00",
}
module.STATE.update({"last_otp": record_b, "otps": [record_b, record_a]})
selected_a = module.select_otp_record(module.get_state(), phone="+8615808505050")
module.consume_otp_record(phone="+8615808505050", record=selected_a)
state_after = module.get_state()
payload = {
"selected_a": selected_a["otp"],
"selected_b_after": module.select_otp_record(state_after, phone="+8618984829950")["otp"],
"selected_a_after": module.select_otp_record(state_after, phone="+8615808505050") is None,
"global_after": module.select_otp_record(state_after)["otp"],
}
print(json.dumps(payload))
`;
const run = runPython(['-c', code], {
timeout: 3000,
env: { GPC_SMS_HELPER_ALLOW_NON_MAC: '1' },
});
if (!run) {
return;
}
assert.equal(run.status, 0, run.stderr);
assert.deepEqual(JSON.parse(run.stdout.trim()), {
selected_a: '111111',
selected_b_after: '222222',
selected_a_after: true,
global_after: '222222',
});
});
@@ -916,7 +916,7 @@ test('GPC billing reads SMS OTP from local helper for sms_otp_wait', async () =>
stateByFrame: {},
fetchImpl: async (url, options = {}) => {
fetchCalls.push({ url, options });
if (url.startsWith('http://127.0.0.1:18767/otp')) {
if (url.startsWith('http://127.0.0.1:18767/latest-otp')) {
return {
ok: true,
status: 200,
@@ -973,17 +973,19 @@ test('GPC billing reads SMS OTP from local helper for sms_otp_wait', async () =>
gopayHelperOtpChannel: 'sms',
gopayHelperLocalSmsHelperEnabled: true,
gopayHelperLocalSmsHelperUrl: 'http://127.0.0.1:18767',
gopayHelperPhoneNumber: '+8613800138000',
gopayHelperCountryCode: '+86',
gopayHelperPhoneNumber: '13800138000',
gopayHelperOrderCreatedAt: 1710000000000,
});
assert.equal(events.states.some((state) => state.plusManualConfirmationMethod === 'gopay-otp'), false);
assert.equal(events.states.some((state) => state.gopayHelperResolvedOtp === '654321'), true);
const helperUrl = new URL(fetchCalls[1].url);
assert.equal(helperUrl.origin + helperUrl.pathname, 'http://127.0.0.1:18767/otp');
assert.equal(helperUrl.origin + helperUrl.pathname, 'http://127.0.0.1:18767/latest-otp');
assert.equal(helperUrl.searchParams.get('task_id'), 'task_sms');
assert.equal(helperUrl.searchParams.get('reference_id'), 'task_sms');
assert.equal(helperUrl.searchParams.get('phone_number'), '+8613800138000');
assert.equal(helperUrl.searchParams.get('phone'), '+8613800138000');
assert.equal(helperUrl.searchParams.get('consume'), '1');
assert.equal(helperUrl.searchParams.get('after_ms'), '1710000000000');
assert.deepEqual(JSON.parse(fetchCalls.find((call) => call.url.endsWith('/api/gp/tasks/task_sms/otp')).options.body), {
otp: '654321',
@@ -999,7 +1001,7 @@ test('GPC billing can read WhatsApp OTP from local helper when enabled', async (
stateByFrame: {},
fetchImpl: async (url, options = {}) => {
fetchCalls.push({ url, options });
if (url.startsWith('http://127.0.0.1:18767/otp')) {
if (url.startsWith('http://127.0.0.1:18767/latest-otp')) {
return {
ok: true,
status: 200,
@@ -1056,11 +1058,15 @@ test('GPC billing can read WhatsApp OTP from local helper when enabled', async (
gopayHelperOtpChannel: 'whatsapp',
gopayHelperLocalSmsHelperEnabled: true,
gopayHelperLocalSmsHelperUrl: 'http://127.0.0.1:18767',
gopayHelperPhoneNumber: '+8613800138000',
gopayHelperCountryCode: '+86',
gopayHelperPhoneNumber: '18984829950',
});
assert.equal(events.states.some((state) => state.plusManualConfirmationMethod === 'gopay-otp'), false);
assert.equal(events.states.some((state) => state.gopayHelperResolvedOtp === '765432'), true);
const helperUrl = new URL(fetchCalls.find((call) => call.url.startsWith('http://127.0.0.1:18767/latest-otp')).url);
assert.equal(helperUrl.searchParams.get('phone'), '+8618984829950');
assert.equal(helperUrl.searchParams.get('consume'), '1');
assert.deepEqual(JSON.parse(fetchCalls.find((call) => call.url.endsWith('/api/gp/tasks/task_wa/otp')).options.body), {
otp: '765432',
});
@@ -1075,7 +1081,7 @@ test('GPC billing helper mode does not open OTP dialog when helper has no code a
stateByFrame: {},
fetchImpl: async (url, options = {}) => {
fetchCalls.push({ url, options });
if (url.startsWith('http://127.0.0.1:18767/otp')) {
if (url.startsWith('http://127.0.0.1:18767/latest-otp')) {
return {
ok: true,
status: 200,
@@ -1139,7 +1145,7 @@ test('GPC billing helper mode requests newer OTP after invalid OTP error', async
stateByFrame: {},
fetchImpl: async (url, options = {}) => {
fetchCalls.push({ url, options });
if (url.startsWith('http://127.0.0.1:18767/otp')) {
if (url.startsWith('http://127.0.0.1:18767/latest-otp')) {
helperCallCount += 1;
return {
ok: true,
@@ -1190,9 +1196,13 @@ test('GPC billing helper mode requests newer OTP after invalid OTP error', async
.map((call) => JSON.parse(call.options.body));
assert.deepEqual(otpBodies, [{ otp: '111111' }, { otp: '222222' }]);
assert.equal(otpPostCount, 2);
const helperUrls = fetchCalls.filter((call) => call.url.startsWith('http://127.0.0.1:18767/otp')).map((call) => new URL(call.url));
const helperUrls = fetchCalls.filter((call) => call.url.startsWith('http://127.0.0.1:18767/latest-otp')).map((call) => new URL(call.url));
assert.equal(helperUrls.length, 2);
assert.equal(helperUrls[0].searchParams.get('phone'), '+8613800138000');
assert.equal(helperUrls[0].searchParams.get('consume'), '1');
assert.equal(helperUrls[0].searchParams.get('after_ms'), '1710000000000');
assert.equal(helperUrls[1].searchParams.get('phone'), '+8613800138000');
assert.equal(helperUrls[1].searchParams.get('consume'), '1');
assert.ok(Number(helperUrls[1].searchParams.get('after_ms')) > 1710000000000);
assert.equal(events.logs.some((entry) => /OTP 校验失败/.test(entry.message)), true);
assert.equal(events.completed[0].step, 7);