add YooMoneyWidget, change payments handler
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import {
|
||||
YooMoneyCheckoutWidget,
|
||||
YooMoneyCheckoutWidgetConfig,
|
||||
YooMoneyErrorCallbackResult
|
||||
} from "types-yoomoneycheckoutwidget";
|
||||
|
||||
let isLoading = false;
|
||||
let isInited = false;
|
||||
export default function YooWidget({ config, onComplete, onSuccess, onFail, onModalClose }: {
|
||||
/**
|
||||
* Описание https://yookassa.ru/developers/payment-acceptance/integration-scenarios/widget/reference#initialization-parameters
|
||||
*/
|
||||
config: YooMoneyCheckoutWidgetConfig,
|
||||
/** после успешной оплаты*/
|
||||
onComplete?: () => void,
|
||||
/** после успешной оплаты, только если не подписались на onComplete*/
|
||||
onSuccess?: () => void,
|
||||
/** только если вы отключили обработку неуспешных попыток в виджете: пользователь выбрал любой способ оплаты, но платеж не прошел; закончился срок действия токена.*/
|
||||
onFail?: () => void,
|
||||
/** после закрытия модального окна платежной формы если customization.modal==true */
|
||||
onModalClose?: () => void,
|
||||
}) {
|
||||
const isModal = config?.customization?.modal;
|
||||
let checkout: YooMoneyCheckoutWidget;
|
||||
const destroy = () => {
|
||||
console.log('checkout.destroy');
|
||||
checkout.destroy();
|
||||
isInited = false;
|
||||
}
|
||||
|
||||
const initializeWidget = useCallback(
|
||||
() => {
|
||||
isInited = true;
|
||||
isLoading = false;
|
||||
if (!isModal) {
|
||||
const userErrorCallBack = config.error_callback;
|
||||
config.error_callback = (error: YooMoneyErrorCallbackResult) => {
|
||||
userErrorCallBack(error);
|
||||
isInited = false;
|
||||
};
|
||||
}
|
||||
checkout = new window.YooMoneyCheckoutWidget(config);
|
||||
console.log('checkout.create');
|
||||
checkout.on('complete', (result) => {
|
||||
console.log('on complete', result);
|
||||
onComplete && onComplete();
|
||||
destroy();
|
||||
});
|
||||
onSuccess && checkout.on('success', (result) => {
|
||||
console.log('on success', result);
|
||||
onSuccess();
|
||||
destroy();
|
||||
});
|
||||
onFail && checkout.on('fail', (result) => {
|
||||
console.warn('on fail', result);
|
||||
onFail();
|
||||
destroy();
|
||||
});
|
||||
|
||||
if (config.customization?.modal) {
|
||||
checkout.on('modal_close', (result) => {
|
||||
console.log('on modal_close', result);
|
||||
onModalClose && onModalClose();
|
||||
destroy();
|
||||
});
|
||||
}
|
||||
checkout.render(config.customization?.modal ? undefined : 'payment-form');
|
||||
|
||||
}, [config, onSuccess]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('isInited');
|
||||
console.log(isInited);
|
||||
|
||||
if (!isLoading && !isInited) {
|
||||
if (!window.YooMoneyCheckoutWidget) {
|
||||
isLoading = true;
|
||||
console.log('load script');
|
||||
const script = document.createElement('script');
|
||||
script.src = 'https://yookassa.ru/checkout-widget/v1/checkout-widget.js';
|
||||
script.async = true;
|
||||
script.onload = initializeWidget;
|
||||
document.head.appendChild(script);
|
||||
return () => {
|
||||
console.log('unload script');
|
||||
document.head.removeChild(script);
|
||||
};
|
||||
} else {
|
||||
console.log('init without loading');
|
||||
initializeWidget();
|
||||
}
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (!isInited && !isModal) {
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
{isModal ? '' : <div id="payment-form" />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -7,6 +7,8 @@ import { useTranslations } from 'next-intl';
|
||||
import { yooKasaCreatePayment } from '@/app/actions/yooKassa';
|
||||
import { useState, ReactNode, useEffect } from 'react';
|
||||
import ModalWindow from '@/app/components/ModalWindow';
|
||||
import YooMoneyWidget from './YooMoneyWidget';
|
||||
import { YooMoneyCheckoutWidgetConfig, YooMoneyErrorCallbackResult } from "types-yoomoneycheckoutwidget";
|
||||
|
||||
interface Tariff {
|
||||
id: number;
|
||||
@@ -50,7 +52,7 @@ export default function PaymentTabTariffs() {
|
||||
} | null>(null);
|
||||
const [isProcessing, setIsProcessing] = useState<boolean>(false);
|
||||
|
||||
async function createPayment(value: number, tariff: number) {
|
||||
/* async function createPayment(value: number, tariff: number) {
|
||||
if (isProcessing) return;
|
||||
|
||||
setIsProcessing(true);
|
||||
@@ -58,7 +60,8 @@ export default function PaymentTabTariffs() {
|
||||
try {
|
||||
const response = await yooKasaCreatePayment(value, tariff, 'TARIFF');
|
||||
if (response) {
|
||||
window.open(response, '_blank', 'noopener,noreferrer');
|
||||
console.log('response ok');
|
||||
//window.open(response, '_blank', 'noopener,noreferrer');
|
||||
closeModal(false);
|
||||
} else {
|
||||
setErrorMessage('payment-error');
|
||||
@@ -68,8 +71,65 @@ export default function PaymentTabTariffs() {
|
||||
} finally {
|
||||
setIsProcessing(false);
|
||||
}
|
||||
} */
|
||||
|
||||
const [confirmationToken, setConfirmationToken] = useState<string | null>(null);
|
||||
const [showWidget, setShowWidget] = useState<boolean>(false);
|
||||
const [yooMoneyConfig, setYooMoneyConfig] = useState<YooMoneyCheckoutWidgetConfig | null>(null);
|
||||
|
||||
|
||||
|
||||
async function createPayment(value: number, tariff: number) {
|
||||
if (isProcessing) return;
|
||||
|
||||
setIsProcessing(true);
|
||||
setErrorMessage(null);
|
||||
|
||||
try {
|
||||
const response = await yooKasaCreatePayment(value, tariff, 'TARIFF');
|
||||
|
||||
if (response) {
|
||||
console.log('response ok', response);
|
||||
setConfirmationToken(response);
|
||||
setShowWidget(true);
|
||||
|
||||
const config: YooMoneyCheckoutWidgetConfig = {
|
||||
confirmation_token: response,
|
||||
error_callback: (result: YooMoneyErrorCallbackResult) => {
|
||||
console.error('error_callback', result.error);
|
||||
},
|
||||
customization: {
|
||||
modal: true
|
||||
}
|
||||
}
|
||||
|
||||
setYooMoneyConfig(config);
|
||||
closeModal(false);
|
||||
} else {
|
||||
setErrorMessage('payment-error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Payment creation error:', error);
|
||||
setErrorMessage('payment-error');
|
||||
} finally {
|
||||
setIsProcessing(false);
|
||||
}
|
||||
}
|
||||
|
||||
const handleWidgetSuccess = () => {
|
||||
console.log('Payment successful');
|
||||
// Здесь можно закрыть модалку или показать сообщение об успехе
|
||||
setShowWidget(false);
|
||||
setConfirmationToken(null);
|
||||
};
|
||||
|
||||
const handleWidgetError = (error: any) => {
|
||||
console.error('Widget error:', error);
|
||||
setErrorMessage('widget-error');
|
||||
setShowWidget(false);
|
||||
setConfirmationToken(null);
|
||||
};
|
||||
|
||||
function openPaymentWindow(value: number, tariff: string, tokens: number, tariffId: number) {
|
||||
setSelectedTariff({ value, tariff, tokens, tariffId });
|
||||
setIsProcessing(false);
|
||||
@@ -149,6 +209,15 @@ export default function PaymentTabTariffs() {
|
||||
);
|
||||
}
|
||||
|
||||
const onComplete = () => {
|
||||
console.log('Payment accepted');
|
||||
};
|
||||
const onModalClose = () => {
|
||||
setYooMoneyConfig(null);
|
||||
setShowWidget(false);
|
||||
console.log('Payment not finished');
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ModalWindow state={openWindow} callBack={closeModal}>
|
||||
@@ -217,6 +286,11 @@ export default function PaymentTabTariffs() {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Модальное окно с виджетом */}
|
||||
{showWidget && yooMoneyConfig && (
|
||||
<YooMoneyWidget config={yooMoneyConfig} onComplete={onComplete} onModalClose={onModalClose} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user