Donations: Finish wiring up the 3ds validation flow

Co-authored-by: Scott Nonnenberg <scott@signal.org>
This commit is contained in:
automated-signal 2025-07-10 12:48:05 -05:00 committed by GitHub
parent 94df85c3e0
commit 3dfd0f98c6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 26 additions and 6 deletions

View file

@ -2917,6 +2917,7 @@ function handleSignalRoute(route: ParsedSignalRoute) {
showWindow();
} else if (route.key === 'donationValidationComplete') {
log.info('donationValidationComplete route handled');
mainWindow.webContents.send('donation-validation-complete', route.args);
} else {
log.info('handleSignalRoute: Unknown signal route:', route.key);
mainWindow.webContents.send('unknown-sgnl-link');

View file

@ -113,12 +113,22 @@ export async function finishDonationWithCard(
}
export async function finish3dsValidation(token: string): Promise<void> {
const existing = _getWorkflowFromRedux();
if (!existing) {
throw new Error('finish3dsValidation: Cannot finish nonexistent workflow!');
let workflow: DonationWorkflow;
try {
const existing = _getWorkflowFromRedux();
if (!existing) {
throw new Error(
'finish3dsValidation: Cannot finish nonexistent workflow!'
);
}
workflow = await _completeValidationRedirect(existing, token);
} catch (error) {
await failDonation(donationErrorTypeSchema.Enum.Failed3dsValidation);
throw error;
}
const workflow = await _completeValidationRedirect(existing, token);
await _saveAndRunWorkflow(workflow);
}
@ -681,7 +691,8 @@ async function failDonation(errorType: DonationErrorType): Promise<void> {
if (
workflow &&
workflow.type !== donationStateSchema.Enum.INTENT_METHOD &&
workflow.type !== donationStateSchema.Enum.INTENT
workflow.type !== donationStateSchema.Enum.INTENT &&
workflow.type !== donationStateSchema.Enum.INTENT_REDIRECT
) {
await _saveWorkflow(undefined);
}

View file

@ -464,9 +464,9 @@ export const setup = (options: {
initializeGroupCredentialFetcher,
initializeNetworkObserver,
initializeUpdateListener,
donations,
// Testing
donations,
storage,
};

View file

@ -17,6 +17,8 @@ export const donationErrorTypeSchema = z.enum([
'PaymentDeclined',
// Only used if we can't support 3DS validation for our first release
'CardNotSupported',
// Used if the user is redirected back from validation, but continuing forward fails
'Failed3dsValidation',
// Any other HTTPError during the process
'DonationProcessingError',
// Any other error

2
ts/window.d.ts vendored
View file

@ -21,6 +21,7 @@ import type {
import type AccountManager from './textsecure/AccountManager';
import type { WebAPIConnectType } from './textsecure/WebAPI';
import type { CallingClass } from './services/calling';
import type * as Donations from './services/donations';
import type * as StorageService from './services/storage';
import type { BackupsService } from './services/backups';
import type * as Groups from './groups';
@ -164,6 +165,7 @@ export type SignalCoreType = {
lightSessionResetQueue?: PQueue;
retryPlaceholders?: RetryPlaceholders;
storage: typeof StorageService;
donations: typeof Donations;
};
SettingsWindowProps?: SettingsWindowPropsType;
Migrations: ReturnType<typeof initializeMigrations>;

View file

@ -373,6 +373,10 @@ ipc.on('cancel-presenting', () => {
window.reduxActions?.calling?.cancelPresenting();
});
ipc.on('donation-validation-complete', (_event, { token }) => {
drop(window.Signal.Services.donations.finish3dsValidation(token));
});
ipc.on('show-conversation-via-token', (_event, token: string) => {
const { showConversationViaToken } = window.Events;
if (showConversationViaToken) {