fix(gpc): allow local helper for whatsapp otp

This commit is contained in:
朴圣佑
2026-05-06 17:36:29 +08:00
parent 9964b5a317
commit 612fccd4c6
4 changed files with 69 additions and 18 deletions
+1 -2
View File
@@ -423,8 +423,7 @@
}
await addLog(`步骤 7:GPC 模式开始 OTP 验证(reference_id: ${referenceId}...`, 'info');
let otp = '';
const useLocalSmsHelper = Boolean(state?.gopayHelperLocalSmsHelperEnabled)
&& normalizeGpcOtpChannel(state?.gopayHelperOtpChannel) === 'sms';
const useLocalSmsHelper = Boolean(state?.gopayHelperLocalSmsHelperEnabled);
if (useLocalSmsHelper) {
try {
await addLog('步骤 7:正在从本地 SMS Helper 等待 GPC OTP...', 'info');
+3 -6
View File
@@ -3147,7 +3147,7 @@ function collectSettingsPayload() {
? selectGpcHelperOtpChannel.value
: (latestState?.gopayHelperOtpChannel || 'whatsapp')
);
const selectedGpcLocalSmsHelperEnabled = selectedGpcOtpChannel === 'sms' && Boolean(
const selectedGpcLocalSmsHelperEnabled = Boolean(
typeof inputGpcHelperLocalSmsEnabled !== 'undefined' && inputGpcHelperLocalSmsEnabled
? inputGpcHelperLocalSmsEnabled.checked
: latestState?.gopayHelperLocalSmsHelperEnabled
@@ -7014,8 +7014,8 @@ function updatePlusModeUI() {
? normalizePlusPaymentMethod(selectPlusPaymentMethod.value)
: method;
const gpcRowsVisible = enabled && selectedMethod === gpcValue;
const localSmsControlsVisible = gpcRowsVisible && gpcOtpChannel === 'sms';
const effectiveLocalSmsEnabled = gpcOtpChannel === 'sms' && localSmsEnabled;
const localSmsControlsVisible = gpcRowsVisible;
const effectiveLocalSmsEnabled = localSmsEnabled;
if (typeof selectPlusPaymentMethod !== 'undefined' && selectPlusPaymentMethod) {
selectPlusPaymentMethod.value = method;
if (selectPlusPaymentMethod.style) {
@@ -11229,9 +11229,6 @@ selectPlusPaymentMethod?.addEventListener('change', () => {
scheduleSettingsAutoSave();
});
input?.addEventListener('change', () => {
if (input === inputGpcHelperLocalSmsEnabled && input.checked && selectGpcHelperOtpChannel) {
selectGpcHelperOtpChannel.value = 'sms';
}
if (input === selectGpcHelperOtpChannel || input === inputGpcHelperLocalSmsEnabled) {
updatePlusModeUI();
}
@@ -932,6 +932,65 @@ test('GPC billing reads OTP from local SMS helper when enabled', async () => {
assert.equal(events.completed[0].step, 7);
});
test('GPC billing can read WhatsApp OTP from local helper when enabled', async () => {
const fetchCalls = [];
const { events, executor } = createExecutorHarness({
frames: [],
stateByFrame: {},
fetchImpl: async (url, options = {}) => {
fetchCalls.push({ url, options });
if (url.startsWith('http://127.0.0.1:18767/otp')) {
return {
ok: true,
status: 200,
json: async () => ({ ok: true, otp: '765432', message_id: 'wa-1' }),
};
}
if (url.endsWith('/api/gopay/otp')) {
return {
ok: true,
status: 200,
json: async () => ({ reference_id: 'ref_wa', challenge_id: 'challenge_wa' }),
};
}
if (url.endsWith('/api/gopay/pin')) {
return {
ok: true,
status: 200,
json: async () => ({ stage: 'gopay_complete' }),
};
}
throw new Error(`unexpected url: ${url}`);
},
});
await executor.executePlusCheckoutBilling({
plusPaymentMethod: 'gpc-helper',
plusCheckoutSource: 'gpc-helper',
gopayHelperReferenceId: 'ref_wa',
gopayHelperApiUrl: 'https://gopay.hwork.pro/',
gopayHelperPin: '654321',
gopayHelperCardKey: 'card_wa',
gopayHelperOtpChannel: 'whatsapp',
gopayHelperLocalSmsHelperEnabled: true,
gopayHelperLocalSmsHelperUrl: 'http://127.0.0.1:18767',
gopayHelperPhoneNumber: '+8613800138000',
});
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[0].url);
assert.equal(helperUrl.origin + helperUrl.pathname, 'http://127.0.0.1:18767/otp');
assert.equal(helperUrl.searchParams.get('reference_id'), 'ref_wa');
assert.equal(helperUrl.searchParams.get('phone_number'), '+8613800138000');
assert.deepEqual(JSON.parse(fetchCalls[1].options.body), {
reference_id: 'ref_wa',
otp: '765432',
card_key: 'card_wa',
});
assert.equal(events.completed[0].step, 7);
});
test('GPC billing retries OTP with compatibility field after HTTP 400', async () => {
const fetchCalls = [];
let currentState = {
+6 -10
View File
@@ -257,24 +257,20 @@ return {
assert.equal(api.rows.rowGpcHelperCardKey.style.display, '');
assert.equal(api.rows.rowGpcHelperPhone.style.display, '');
assert.equal(api.rows.rowGpcHelperOtpChannel.style.display, '');
assert.equal(api.rows.rowGpcHelperLocalSmsEnabled.style.display, 'none');
assert.equal(api.rows.rowGpcHelperLocalSmsEnabled.style.display, '');
assert.equal(api.rows.rowGpcHelperLocalSmsUrl.style.display, 'none');
assert.match(api.plusPaymentMethodCaption.textContent, /GPC/);
api.selectGpcHelperOtpChannel.value = 'sms';
api.updatePlusModeUI();
assert.equal(api.rows.rowGpcHelperLocalSmsEnabled.style.display, '');
assert.equal(api.rows.rowGpcHelperLocalSmsUrl.style.display, 'none');
api.inputGpcHelperLocalSmsEnabled.checked = true;
api.updatePlusModeUI();
assert.equal(api.selectGpcHelperOtpChannel.value, 'whatsapp');
assert.equal(api.rows.rowGpcHelperLocalSmsUrl.style.display, '');
api.selectGpcHelperOtpChannel.value = 'whatsapp';
api.selectGpcHelperOtpChannel.value = 'sms';
api.updatePlusModeUI();
assert.equal(api.inputGpcHelperLocalSmsEnabled.checked, false);
assert.equal(api.rows.rowGpcHelperLocalSmsEnabled.style.display, 'none');
assert.equal(api.rows.rowGpcHelperLocalSmsUrl.style.display, 'none');
assert.equal(api.inputGpcHelperLocalSmsEnabled.checked, true);
assert.equal(api.rows.rowGpcHelperLocalSmsEnabled.style.display, '');
assert.equal(api.rows.rowGpcHelperLocalSmsUrl.style.display, '');
api.selectPlusPaymentMethod.value = 'gopay';
api.updatePlusModeUI();