add YooMoneyWidget, change payments handler
This commit is contained in:
Generated
+10
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "no-copy-frontend",
|
"name": "no-copy-frontend",
|
||||||
"version": "0.44.0",
|
"version": "0.49.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "no-copy-frontend",
|
"name": "no-copy-frontend",
|
||||||
"version": "0.44.0",
|
"version": "0.49.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@a2seven/yoo-checkout": "^1.1.4",
|
"@a2seven/yoo-checkout": "^1.1.4",
|
||||||
"@react-input/mask": "^2.0.4",
|
"@react-input/mask": "^2.0.4",
|
||||||
@@ -39,6 +39,7 @@
|
|||||||
"eslint": "^9",
|
"eslint": "^9",
|
||||||
"eslint-config-next": "16.0.3",
|
"eslint-config-next": "16.0.3",
|
||||||
"sass": "^1.94.2",
|
"sass": "^1.94.2",
|
||||||
|
"types-yoomoneycheckoutwidget": "^0.0.2",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -7732,6 +7733,13 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/types-yoomoneycheckoutwidget": {
|
||||||
|
"version": "0.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/types-yoomoneycheckoutwidget/-/types-yoomoneycheckoutwidget-0.0.2.tgz",
|
||||||
|
"integrity": "sha512-Vab30GrWEE5qq65CbBcJW5deFjJ9jRVlmh+ZneaUsqnPKPlWHGwhA1ukx+o70LjqEdgK+HgMkxNlFsqchLX7ww==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "5.9.3",
|
"version": "5.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
"eslint": "^9",
|
"eslint": "^9",
|
||||||
"eslint-config-next": "16.0.3",
|
"eslint-config-next": "16.0.3",
|
||||||
"sass": "^1.94.2",
|
"sass": "^1.94.2",
|
||||||
|
"types-yoomoneycheckoutwidget": "^0.0.2",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import { YooCheckout, ICreatePayment } from '@a2seven/yoo-checkout';
|
import { YooCheckout, ICreatePayment } from '@a2seven/yoo-checkout';
|
||||||
import { getSessionData, deleteSession } from '@/app/actions/session';
|
import { getSessionData, deleteSession } from '@/app/actions/session';
|
||||||
import { API_BASE_URL } from '@/app/actions/definitions';
|
import { API_BASE_URL } from '@/app/actions/definitions';
|
||||||
|
import { id } from 'zod/v4/locales';
|
||||||
|
|
||||||
const checkout = new YooCheckout({ shopId: '1276731', secretKey: 'test_0Yns_0NHV5GJf6ypJ5HC4NSfnLO8SJkw-1PwrVWsDl4' });
|
const checkout = new YooCheckout({ shopId: '1276731', secretKey: 'test_0Yns_0NHV5GJf6ypJ5HC4NSfnLO8SJkw-1PwrVWsDl4' });
|
||||||
|
|
||||||
@@ -36,6 +37,7 @@ export async function makePaymentOperation(email: string, tariffId: number, oper
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function yooKasaCreatePayment(amount: number, tariff: number, operationType: 'TARIFF' | 'TOKEN') {
|
export async function yooKasaCreatePayment(amount: number, tariff: number, operationType: 'TARIFF' | 'TOKEN') {
|
||||||
|
console.log('yooKasaCreatePayment');
|
||||||
|
|
||||||
const userEmail = await getSessionData('email');
|
const userEmail = await getSessionData('email');
|
||||||
const timestamp = Date.now();
|
const timestamp = Date.now();
|
||||||
@@ -51,21 +53,37 @@ export async function yooKasaCreatePayment(amount: number, tariff: number, opera
|
|||||||
value: amount.toLocaleString().replace(/\s/g, ''),
|
value: amount.toLocaleString().replace(/\s/g, ''),
|
||||||
currency: 'RUB'
|
currency: 'RUB'
|
||||||
},
|
},
|
||||||
payment_method_data: {
|
/* payment_method_data: {
|
||||||
type: 'bank_card'
|
type: 'bank_card'
|
||||||
},
|
}, */
|
||||||
|
/* payment_method_id: "3138d708-000f-5001-9000-19865cfcca68", */
|
||||||
confirmation: {
|
confirmation: {
|
||||||
type: 'redirect',
|
type: 'embedded',
|
||||||
return_url: 'test'
|
/* type: 'redirect',
|
||||||
|
return_url: 'test' */
|
||||||
},
|
},
|
||||||
metadata: {
|
metadata: {
|
||||||
userMail: userEmail,
|
userMail: userEmail,
|
||||||
tariff: tariff
|
tariff: tariff
|
||||||
},
|
},
|
||||||
|
merchant_customer_id: userEmail,
|
||||||
capture: true
|
capture: true
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const payment = await checkout.createPayment(createPayload, idempotenceKey);
|
||||||
|
const response = await makePaymentOperation(userEmail, tariff, payment.id, operationType);
|
||||||
|
console.log(payment);
|
||||||
|
if (payment && response) {
|
||||||
|
return payment?.confirmation.confirmation_token;
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try {
|
||||||
const payment = await checkout.createPayment(createPayload, idempotenceKey);
|
const payment = await checkout.createPayment(createPayload, idempotenceKey);
|
||||||
const response = await makePaymentOperation(userEmail, tariff, payment.id, operationType);
|
const response = await makePaymentOperation(userEmail, tariff, payment.id, operationType);
|
||||||
if (response && payment) {
|
if (response && payment) {
|
||||||
@@ -75,7 +93,7 @@ export async function yooKasaCreatePayment(amount: number, tariff: number, opera
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return null
|
return null
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchPaymentsHistory() {
|
export async function fetchPaymentsHistory() {
|
||||||
|
|||||||
@@ -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 { yooKasaCreatePayment } from '@/app/actions/yooKassa';
|
||||||
import { useState, ReactNode, useEffect } from 'react';
|
import { useState, ReactNode, useEffect } from 'react';
|
||||||
import ModalWindow from '@/app/components/ModalWindow';
|
import ModalWindow from '@/app/components/ModalWindow';
|
||||||
|
import YooMoneyWidget from './YooMoneyWidget';
|
||||||
|
import { YooMoneyCheckoutWidgetConfig, YooMoneyErrorCallbackResult } from "types-yoomoneycheckoutwidget";
|
||||||
|
|
||||||
interface Tariff {
|
interface Tariff {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -50,7 +52,7 @@ export default function PaymentTabTariffs() {
|
|||||||
} | null>(null);
|
} | null>(null);
|
||||||
const [isProcessing, setIsProcessing] = useState<boolean>(false);
|
const [isProcessing, setIsProcessing] = useState<boolean>(false);
|
||||||
|
|
||||||
async function createPayment(value: number, tariff: number) {
|
/* async function createPayment(value: number, tariff: number) {
|
||||||
if (isProcessing) return;
|
if (isProcessing) return;
|
||||||
|
|
||||||
setIsProcessing(true);
|
setIsProcessing(true);
|
||||||
@@ -58,7 +60,8 @@ export default function PaymentTabTariffs() {
|
|||||||
try {
|
try {
|
||||||
const response = await yooKasaCreatePayment(value, tariff, 'TARIFF');
|
const response = await yooKasaCreatePayment(value, tariff, 'TARIFF');
|
||||||
if (response) {
|
if (response) {
|
||||||
window.open(response, '_blank', 'noopener,noreferrer');
|
console.log('response ok');
|
||||||
|
//window.open(response, '_blank', 'noopener,noreferrer');
|
||||||
closeModal(false);
|
closeModal(false);
|
||||||
} else {
|
} else {
|
||||||
setErrorMessage('payment-error');
|
setErrorMessage('payment-error');
|
||||||
@@ -68,7 +71,64 @@ export default function PaymentTabTariffs() {
|
|||||||
} finally {
|
} finally {
|
||||||
setIsProcessing(false);
|
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) {
|
function openPaymentWindow(value: number, tariff: string, tokens: number, tariffId: number) {
|
||||||
setSelectedTariff({ value, tariff, tokens, tariffId });
|
setSelectedTariff({ value, tariff, tokens, tariffId });
|
||||||
@@ -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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<ModalWindow state={openWindow} callBack={closeModal}>
|
<ModalWindow state={openWindow} callBack={closeModal}>
|
||||||
@@ -217,6 +286,11 @@ export default function PaymentTabTariffs() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Модальное окно с виджетом */}
|
||||||
|
{showWidget && yooMoneyConfig && (
|
||||||
|
<YooMoneyWidget config={yooMoneyConfig} onComplete={onComplete} onModalClose={onModalClose} />
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user