From 04d45b227568b298c67658a7a6967bb539541bf7 Mon Sep 17 00:00:00 2001 From: zubiden <19638254+zubiden@users.noreply.github.com> Date: Mon, 27 Apr 2026 14:29:14 +0200 Subject: [PATCH] Payment Modal: Keep verification in the same tab (#6889) --- src/api/gramjs/methods/payments.ts | 28 +++++++++++++---------- src/api/types/updates.ts | 7 +----- src/components/payment/ConfirmPayment.tsx | 2 +- src/global/actions/api/payments.ts | 16 ++++++++++++- src/global/actions/apiUpdaters/misc.ts | 11 --------- src/global/reducers/payments.ts | 8 +------ 6 files changed, 34 insertions(+), 38 deletions(-) diff --git a/src/api/gramjs/methods/payments.ts b/src/api/gramjs/methods/payments.ts index 6649f044f..9d7a544bc 100644 --- a/src/api/gramjs/methods/payments.ts +++ b/src/api/gramjs/methods/payments.ts @@ -36,10 +36,15 @@ import { serializeBytes, } from '../helpers/misc'; import localDb from '../localDb'; -import { sendApiUpdate } from '../updates/apiUpdateEmitter'; import { handleGramJsUpdate, invokeRequest } from './client'; import { getTemporaryPaymentPassword } from './twoFaSettings'; +type SendPaymentFormResult = { + completed: true; +} | { + verificationUrl: string; +}; + export async function validateRequestedInfo({ inputInvoice, requestInfo, @@ -90,7 +95,7 @@ export async function sendPaymentForm({ savedCredentialId?: string; temporaryPassword?: string; tipAmount?: number; -}) { +}): Promise { const inputCredentials = temporaryPassword && savedCredentialId ? new GramJs.InputPaymentCredentialsSaved({ id: savedCredentialId, @@ -109,20 +114,19 @@ export async function sendPaymentForm({ ...(tipAmount && { tipAmount: BigInt(tipAmount) }), })); - if (!result) return false; + if (!result) return undefined; if (result instanceof GramJs.payments.PaymentVerificationNeeded) { - sendApiUpdate({ - '@type': 'updatePaymentVerificationNeeded', - url: result.url, - }); - - return undefined; - } else { - handleGramJsUpdate(result.updates); + return { + verificationUrl: result.url, + }; } - return Boolean(result); + handleGramJsUpdate(result.updates); + + return { + completed: true, + }; } export async function sendStarPaymentForm({ diff --git a/src/api/types/updates.ts b/src/api/types/updates.ts index 9d0afca5a..3944c2303 100644 --- a/src/api/types/updates.ts +++ b/src/api/types/updates.ts @@ -610,11 +610,6 @@ export type ApiUpdatePeerBlocked = { isBlockedFromStories?: boolean; }; -export type ApiUpdatePaymentVerificationNeeded = { - '@type': 'updatePaymentVerificationNeeded'; - url: string; -}; - export type ApiUpdatePaymentStateCompleted = { '@type': 'updatePaymentStateCompleted'; paymentState: TabState['payment']; @@ -953,7 +948,7 @@ export type ApiUpdate = ( ApiUpdateServerTimeOffset | ApiUpdateMessageReactions | ApiUpdateSavedReactionTags | ApiUpdateGroupCallParticipants | ApiUpdateGroupCallConnection | ApiUpdateGroupCall | ApiUpdateGroupCallStreams | ApiUpdateGroupCallConnectionState | ApiUpdateGroupCallLeavePresentation | ApiUpdateGroupCallChatId | - ApiUpdatePendingJoinRequests | ApiUpdatePaymentVerificationNeeded | ApiUpdatePaymentStateCompleted | + ApiUpdatePendingJoinRequests | ApiUpdatePaymentStateCompleted | ApiUpdatePhoneCall | ApiUpdatePhoneCallSignalingData | ApiUpdatePhoneCallMediaState | ApiUpdatePhoneCallConnectionState | ApiUpdateBotMenuButton | ApiUpdateTranscribedAudio | ApiUpdateUserEmojiStatus | ApiUpdateMessageExtendedMedia | ApiUpdateConfig | ApiUpdateTopicNotifySettings | ApiUpdatePinnedTopic | diff --git a/src/components/payment/ConfirmPayment.tsx b/src/components/payment/ConfirmPayment.tsx index a9f8d6a79..da9fc21b2 100644 --- a/src/components/payment/ConfirmPayment.tsx +++ b/src/components/payment/ConfirmPayment.tsx @@ -85,7 +85,7 @@ const ConfirmPayment = ({ src={url} title={lang('Checkout.WebConfirmation.Title')} allow="payment" - sandbox="allow-modals allow-forms allow-scripts allow-top-navigation allow-same-origin" + sandbox="allow-modals allow-forms allow-scripts allow-same-origin" className="ConfirmPayment__content" /> diff --git a/src/global/actions/api/payments.ts b/src/global/actions/api/payments.ts index 1d75ed5e6..e4901decd 100644 --- a/src/global/actions/api/payments.ts +++ b/src/global/actions/api/payments.ts @@ -111,6 +111,7 @@ addActionHandler('openInvoice', async (global, actions, payload): Promise form, isPaymentModalOpen: true, isExtendedMedia: (payload as any).isExtendedMedia, + confirmPaymentUrl: undefined, status: undefined, }, tabId); global = setPaymentStep(global, PaymentStep.Checkout, tabId); @@ -280,11 +281,24 @@ addActionHandler('sendPaymentForm', async (global, actions, payload): Promise { setGlobal(global); break; - case 'updatePaymentVerificationNeeded': - Object.values(global.byTabId).forEach(({ id: tabId }) => { - global = setConfirmPaymentUrl(global, update.url, tabId); - global = setPaymentStep(global, PaymentStep.ConfirmPayment, tabId); - }); - setGlobal(global); - break; - case 'updateWebViewResultSent': Object.values(global.byTabId).forEach((tabState) => { Object.entries(tabState.webApps.openedWebApps).forEach(([webAppKey, webApp]) => { diff --git a/src/global/reducers/payments.ts b/src/global/reducers/payments.ts index 19a6ad2ad..e96edcb87 100644 --- a/src/global/reducers/payments.ts +++ b/src/global/reducers/payments.ts @@ -87,13 +87,6 @@ export function setSmartGlocalCardInfo( return updatePayment(global, { smartGlocalCredentials: { ...cardInfo } }, tabId); } -export function setConfirmPaymentUrl( - global: T, url?: string, - ...[tabId = getCurrentTabId()]: TabArgs -): T { - return updatePayment(global, { confirmPaymentUrl: url }, tabId); -} - export function setReceipt( global: T, receipt?: ApiReceiptRegular, @@ -131,6 +124,7 @@ export function closeInvoice( ...[tabId = getCurrentTabId()]: TabArgs ): T { global = updatePayment(global, { + confirmPaymentUrl: undefined, isPaymentModalOpen: undefined, isExtendedMedia: undefined, }, tabId);