diff --git a/ts/components/Preferences.stories.tsx b/ts/components/Preferences.stories.tsx index 26d69579de..e96af73065 100644 --- a/ts/components/Preferences.stories.tsx +++ b/ts/components/Preferences.stories.tsx @@ -224,7 +224,6 @@ function renderDonationsPane(props: { initialCurrency="usd" resumeWorkflow={action('resumeWorkflow')} isOnline - isStaging page={props.page} setPage={props.setPage} submitDonation={action('submitDonation')} diff --git a/ts/components/PreferencesDonations.tsx b/ts/components/PreferencesDonations.tsx index 55cb81e8e7..68500cef58 100644 --- a/ts/components/PreferencesDonations.tsx +++ b/ts/components/PreferencesDonations.tsx @@ -65,7 +65,6 @@ export type PropsDataType = { i18n: LocalizerType; initialCurrency: string; isOnline: boolean; - isStaging: boolean; page: SettingsPage; didResumeWorkflowAtStartup: boolean; lastError: DonationErrorType | undefined; @@ -124,7 +123,6 @@ type PreferencesHomeProps = Pick< | 'i18n' | 'setPage' | 'isOnline' - | 'isStaging' | 'donationReceipts' | 'workflow' > & { @@ -208,7 +206,6 @@ function DonationsHome({ navigateToPage, setPage, isOnline, - isStaging, donationReceipts, workflow, }: PreferencesHomeProps): JSX.Element { @@ -258,7 +255,7 @@ function DonationsHome({ {renderDonationHero()} - {isStaging && isOnline ? ( + {isOnline ? ( donateButton ) : ( @@ -547,7 +544,6 @@ export function PreferencesDonations({ i18n, initialCurrency, isOnline, - isStaging, page, workflow, didResumeWorkflowAtStartup, @@ -773,7 +769,6 @@ export function PreferencesDonations({ isOnline={isOnline} navigateToPage={navigateToPage} donationReceipts={donationReceipts} - isStaging={isStaging} renderDonationHero={renderDonationHero} setPage={setPage} workflow={workflow} diff --git a/ts/services/donations.ts b/ts/services/donations.ts index 8c0759a953..d587d4bf63 100644 --- a/ts/services/donations.ts +++ b/ts/services/donations.ts @@ -164,10 +164,14 @@ export async function finishDonationWithCard( try { workflow = await _createPaymentMethodForIntent(existing, paymentDetail); } catch (error) { - if (error.code >= 400 && error.code <= 499) { - await failDonation(donationErrorTypeSchema.Enum.PaymentDeclined); + const errorType: string | undefined = error.response?.error?.type; + if (error.code >= 400 && error.code <= 499 && errorType === 'card_error') { + await failDonation( + donationErrorTypeSchema.Enum.PaymentDeclined, + errorType + ); } else { - await failDonation(donationErrorTypeSchema.Enum.GeneralError); + await failDonation(donationErrorTypeSchema.Enum.GeneralError, errorType); } throw error; @@ -405,16 +409,27 @@ export async function _runDonationWorkflow(): Promise { await _saveWorkflow(updated); } catch (error) { + const errorType: string | undefined = error.response?.error?.type; + if ( error.name === 'HTTPError' && error.code >= 400 && error.code <= 499 ) { log.warn(`${logId}: Got a ${error.code} error. Failing donation.`); - if (type === donationStateSchema.Enum.INTENT_METHOD) { - await failDonation(donationErrorTypeSchema.Enum.PaymentDeclined); + if ( + type === donationStateSchema.Enum.INTENT_METHOD && + errorType === 'card_error' + ) { + await failDonation( + donationErrorTypeSchema.Enum.PaymentDeclined, + errorType + ); } else { - await failDonation(donationErrorTypeSchema.Enum.GeneralError); + await failDonation( + donationErrorTypeSchema.Enum.GeneralError, + errorType + ); } throw error; } @@ -426,7 +441,10 @@ export async function _runDonationWorkflow(): Promise { log.warn( `${logId}: Donation step threw unexpectedly. Failing donation. ${Errors.toLogFormat(error)}` ); - await failDonation(donationErrorTypeSchema.Enum.GeneralError); + await failDonation( + donationErrorTypeSchema.Enum.GeneralError, + errorType + ); throw error; } } @@ -800,7 +818,10 @@ export async function _redeemReceipt( // Helper functions -async function failDonation(errorType: DonationErrorType): Promise { +async function failDonation( + errorType: DonationErrorType, + details: string | undefined = undefined +): Promise { const workflow = _getWorkflowFromRedux(); const logId = `failDonation(${workflow?.id ? redactId(workflow.id) : 'NONE'})`; @@ -814,7 +835,9 @@ async function failDonation(errorType: DonationErrorType): Promise { await _saveWorkflow(undefined); } - log.info(`failDonation: Failing with type ${errorType}`); + log.info( + `failDonation: Failing with type ${errorType} ${details ? `details=${details}` : ''}` + ); if (!isDonationPageVisible()) { if (errorType === donationErrorTypeSchema.Enum.Failed3dsValidation) { log.info( diff --git a/ts/state/ducks/donations.ts b/ts/state/ducks/donations.ts index a52e5ea811..237b549e96 100644 --- a/ts/state/ducks/donations.ts +++ b/ts/state/ducks/donations.ts @@ -160,11 +160,6 @@ function submitDonation({ UpdateWorkflowAction > { return async (_dispatch, getState) => { - if (!isStagingServer()) { - log.error('submitDonation: Only available on staging server'); - return; - } - try { const { currentWorkflow } = getState().donations; if ( diff --git a/ts/state/smart/PreferencesDonations.tsx b/ts/state/smart/PreferencesDonations.tsx index e46d2988d7..256b3976d1 100644 --- a/ts/state/smart/PreferencesDonations.tsx +++ b/ts/state/smart/PreferencesDonations.tsx @@ -13,7 +13,6 @@ import type { SettingsPage } from '../../types/Nav'; import { useDonationsActions } from '../ducks/donations'; import type { StateType } from '../reducer'; import { useConversationsActions } from '../ducks/conversations'; -import { isStagingServer } from '../../util/isStagingServer'; import { generateDonationReceiptBlob } from '../../util/generateDonationReceipt'; import { useToastActions } from '../ducks/toast'; import { @@ -51,7 +50,6 @@ export const SmartPreferencesDonations = memo( const getPreferredBadge = useSelector(getPreferredBadgeSelector); const isOnline = useSelector(getNetworkIsOnline); - const isStaging = isStagingServer(); const i18n = useSelector(getIntl); const theme = useSelector(getTheme); @@ -138,7 +136,6 @@ export const SmartPreferencesDonations = memo( contentsRef={contentsRef} initialCurrency={initialCurrency} isOnline={isOnline} - isStaging={isStaging} page={page} didResumeWorkflowAtStartup={donationsState.didResumeWorkflowAtStartup} lastError={donationsState.lastError}