T-Kassa
Enable seamless payments with TKassa via Medusa plugin
Платежи T-Kassa для Medusa
Плагин Medusa для приёма платежей через T-Kassa.
Read README in English →
Возможности
- 🔗 Бесшовная интеграция с платёжной системой YooKassa
- 🧾 Формирование онлайн-чеков в соответствии с 54-ФЗ
- 1️⃣ Одностадийные (автосписание) и 2️⃣ двухстадийные (авторизация/холдирование) сценарии оплаты
- 🔄 Возвраты и отмена заказов
- 🔔 Вебхук-уведомления о статусах платежей в реальном времени
- 🛡 Проверка вебхуков для обеспечения безопасности
- 🔍 Подробное логирование для отладки
💬 Чат поддержки плагина T-Kassa
Есть вопросы или идеи по новым функциям плагина?
Присоединяйтесь к чату в Telegram – @medusajs_tkassa
👥 Чат сообщества Medusa.js
Общайтесь в Telegram с другими разработчиками Medusa – @medusajs_chat
Требования
- Medusa v2.7.0 или выше
- Node.js v20 или выше
- Аккаунт T-Business с подключённым интернет-эквайрингом T-Kassa – зарегистрируйтесь или войдите
Установка
123yarn add @gorgo/medusa-payment-tkassa# илиnpm install @gorgo/medusa-payment-tkassa
Настройка
Добавьте конфигурацию провайдера в файл Copy to clipboardmedusa-config.js
в приложении Medusa Admin:
1234567891011121314151617181920// ...module.exports = defineConfig({// ...modules: [{resolve: "@medusajs/medusa/payment",options: {providers: [{resolve: "@gorgo/medusa-payment-tkassa/providers/payment-tkassa",id: "tkassa",options: {terminalKey: process.env.TKASSA_TERMINAL_KEY,password: process.env.TKASSA_PASSWORD,capture: true,useReceipt: true,ffdVersion: "1.05",taxation: "osn",taxItemDefault: "none",taxShippingDefault: "none"
Добавьте переменные окружения Copy to clipboardTerminalKey
и Copy to clipboardPassword
из личного кабинета T-Business:
12TKASSA_TERMINAL_KEY=123456789TKASSA_PASSWORD=supersecret
Параметры провайдера
Параметр Описание Обязательный По умолчанию Copy to clipboardterminalKey
Ключ терминала, предоставленный T-Kassa (обязателен для аутентификации) Да - Copy to clipboardpassword
Пароль для подписи запросов (обязателен для аутентификации) Да - Copy to clipboardcapture
Определяет тип проведения платежа:
- Copy to clipboardtrue
— одностадийная оплата (Copy to clipboardO
в API)
- Copy to clipboardfalse
— двухстадийная оплата (Copy to clipboardT
в API) Нет Copy to clipboardtrue
Copy to clipboarduseReceipt
Включает формирование онлайн-чеков по 54-ФЗ Нет Copy to clipboardfalse
Copy to clipboardffdVersion
Версия ФФД: Copy to clipboard1.2
или Copy to clipboard1.05
Применимо только при Copy to clipboarduseReceipt=true
Нет - Copy to clipboardtaxation
Система налогообложения:
- Copy to clipboardosn
— общая СН
- Copy to clipboardusn_income
— упрощенная СН (доходы)
- Copy to clipboardusn_income_outcome
— упрощенная СН (доходы минус расходы)
- Copy to clipboardesn
— единый сельскохозяйственный налог
- Copy to clipboardpatent
— патентная СН
Применимо только при Copy to clipboarduseReceipt=true
Нет - Copy to clipboardtaxItemDefault
Ставка НДС по товарам:
- Copy to clipboardnone
— без НДС
- Copy to clipboardvat0
— 0%
- Copy to clipboardvat5
— 5%
- Copy to clipboardvat7
— 7%
- Copy to clipboardvat10
— 10%
- Copy to clipboardvat20
— 20%
- Copy to clipboardvat105
— 5/105
- Copy to clipboardvat107
— 7/107
- Copy to clipboardvat110
— 10/110
- Copy to clipboardvat120
— 20/120
Применимо только при Copy to clipboarduseReceipt=true
Нет - Copy to clipboardtaxShippingDefault
Ставка НДС для доставки (аналогично Copy to clipboardtaxItemDefault
)
Применимо только при Copy to clipboarduseReceipt=true
Нет -
Интеграция с Storefront (витриной магазина)
Для интеграции платёжного провайдера T-Kassa с storefront на Next.js начните с добавления необходимых UI-компонентов. Таким образом провайдер будет отображаться на странице оформления заказа наряду с другими доступными методами оплаты.
Когда пользователь выбирает T-Kassa, витрина должна вызвать метод Copy to clipboardinitiatePayment
с нужными параметрами. Это создаст платёжную сессию через API T-Kassa и подготовит покупателя к перенаправлению. После этого кнопка Place Order должна отправить пользователя на страницу оплаты T-Kassa, где он сможет выбрать предпочтительный способ оплаты.
После завершения оплаты T-Kassa одновременно отправит вебхук и перенаправит покупателя обратно в витрину. То событие, которое придёт первым, завершит корзину и создаст новый заказ в Medusa.
Для запуска на Next.js необходимо внести следующие изменения:
1. Конфигурация платежного провайдера
Чтобы сделать T-Kassa доступным в качестве способа оплаты на странице оформления заказа витрины магазина, необходимо добавить её конфигурацию в маппинг платёжных провайдеров в файле с константами вашего storefront. Этот маппинг определяет как каждый провайдер отображается в интерфейсе.
Откройте Copy to clipboardsrc/lib/constants.tsx
и добавьте следующий код:
123456789101112131415export const paymentInfoMap: Record<string,{ title: string; icon: React.ReactNode }> = {// ... другие провайдерыpp_tkassa_tkassa: {title: "T-Kassa",icon: <CreditCard />,},}// Вспомогательная функция для проверки, является ли провайдер T-Kassaexport const isTkassa = (providerId?: string) => {return providerId?.startsWith("pp_tkassa")}
Вы расширяете объект Copy to clipboardpaymentInfoMap
, добавляя в него запись Copy to clipboardpp_tkassa_tkassa
. Эта запись определяет заголовок и иконку, которые будут отображаться для T-Kassa на странице оформления заказа.
Вспомогательная функция Copy to clipboardisTkassa
проверяет, принадлежит ли переданный Copy to clipboardproviderId
к T-Kassa. Это используется при рендеринге UI-компонентов, специфичных для конкретного провайдера.
2. Настройки Сookie
При подключении T-Kassa настройте политику cookie так, чтобы поддерживались междоменные редиректы. Это нужно для сохранения платёжной сессии при возврате пользователя в магазин.
Откройте Copy to clipboardsrc/lib/data/cookies.ts
и обновите конфигурацию файлов cookie следующим образом:
123456export const setCartId = async (cartId: string) => {cookies.set("_medusa_cart_id", cartId, {// ... другие настройки cookiesameSite: "lax", // Переключено с режима «Strict» для междоменных редиректов})}
Эта вспомогательная функция сохраняет идентификатор корзины в cookie с именем Copy to clipboard_medusa_cart_id
.
Опция Copy to clipboardsameSite
установлена в значение Copy to clipboardlax
вместо Copy to clipboardstrict
. Это изменение гарантирует, что cookie будет отправляться при кросс-доменных запросах во время процесса редиректа через T-Kassa, предотвращая потерю платёжной сессии.
3. Инициализация платёжной сессии
Чтобы перенаправить покупателя в T-Kassa, платёжная сессия должна быть корректно инициализирована с обязательными параметрами, включая return URL для обоих случаев: успешной и неуспешной оплаты.
Откройте Copy to clipboardsrc/modules/checkout/components/payment/index.tsx
и обновите логику инициализации платежа, включив в нее данные корзины и URL возврата для T-Kassa:
12345678await initiatePaymentSession(cart, {provider_id: selectedPaymentMethod,data: {SuccessURL: `${getBaseURL()}/api/capture-payment/${cart?.id}?country_code=${countryCode}`,FailURL: `${getBaseURL()}/api/capture-payment/${cart?.id}?country_code=${countryCode}`,cart: cart,}})
При инициализации платёжной сессии для T-Kassa параметры Copy to clipboardSuccessURL
и Copy to clipboardFailURL
определяют, куда будет перенаправлен покупатель после попытки оплаты. Оба URL динамически формируются на основе базового URL storefront, идентификатора корзины и выбранного кода страны.
Объект Copy to clipboardcart
включается в данные инициализации для формирования чека в соответствии с Федеральным законом № 54.
4. Компонент кнопки оплаты
В storefront для каждого платёжного провайдера необходим отдельный компонент кнопки оплаты. Он отвечает за обработку оформления заказа после подтверждения пользователем и, используя данные платёжного сеанса, перенаправляет его на страницу оплаты T-Kassa.
Откройте Copy to clipboardsrc/modules/checkout/components/payment-button/index.tsx
и добавьте следующий код:
1234567891011121314151617181920const TkassaPaymentButton: React.FC<TkassaPaymentProps> = ({ cart, notReady }) => {const [submitting, setSubmitting] = useState(false)const [errorMessage, setErrorMessage] = useState<string | null>(null)const router = useRouter()const paymentSession = cart.payment_collection?.payment_sessions?.find(session => session.provider_id === "pp_tkassa_tkassa")const handlePayment = () => {setSubmitting(true)const paymentUrl = (paymentSession?.data as any).PaymentURLif (paymentUrl) {router.push(paymentUrl)} else {setErrorMessage("Payment URL отсутствует")setSubmitting(false)}}}
Этот компонент находит Copy to clipboardpayment_session
для T-Kassa в текущей корзине и извлекает Copy to clipboardPaymentURL
, предоставленный бэкендом. При нажатии кнопки Place order покупатель перенаправляется на этот URL для завершения транзакции на странице оплаты T-Kassa.
Если Copy to clipboardPaymentURL
отсутствует, компонент выводит сообщение об ошибке, не позволяя продолжить. Состояние Copy to clipboardisLoading
обеспечивает визуальную обратную связь во время подготовки перенаправления.
Компонент Copy to clipboardPaymentButton
определяет, принадлежит ли текущая платёжная сессия к T-Kassa, с помощью вспомогательной функции Copy to clipboardisTkassa
. Если да, он рендерит Copy to clipboardTkassaPaymentButton
для обработки процесса оплаты.
Интеграция этого компонента гарантирует, что процесс оплаты через T-Kassa будет запускаться при оформлении заказа.
5. API-роут подтверждения платежа
После того как покупатель завершает оплату на странице T-Kassa, он перенаправляется обратно на витрину магазина. Необходимо создать API-роут, который обработает этот callback, проверит статус платежа и завершит корзину.
Создайте файл Copy to clipboardsrc/app/api/capture-payment/[cartId]/route.ts
со следующим содержимым:
1234567891011121314151617181920import { NextRequest, NextResponse } from "next/server"import { revalidateTag } from "next/cache"import {getCacheTag,getAuthHeaders,removeCartId} from "@lib/data/cookies"import { sdk } from "@lib/config"import { placeOrder } from "@lib/data/cart"type Params = Promise<{ cartId: string }>export async function GET(req: NextRequest, { params }: { params: Params }) {const { cartId } = await paramsconst { origin, searchParams } = req.nextUrlconst countryCode = searchParams.get("country_code") || ""const headers = { ...(await getAuthHeaders()) }// Получить актуальные значения корзины
Этот API-роут обрабатывает редирект от T-Kassa после попытки оплаты. Он получает актуальное состояние корзины, чтобы убедиться, что все изменения, внесённые во время оплаты, были отражены.
Если в корзине нет связанного идентификатора заказа, обработчик роута пытается оформить заказ. В случае успеха покупатель перенаправляется на страницу подтверждения заказа. Если же при обработке корзины возникла ошибка, покупатель возвращается на страницу оформления заказа с указанием ошибки и может повторить процесс оплаты заказа.
Когда оплата проходит успешно, роут повторно валидирует кэшированные данные корзины и заказа, удаляет cookie корзины и перенаправляет покупателя на страницу подтверждения заказа. Это гарантирует корректное завершение платёжного процесса и сохранение актуальных данных в storefront.
Пример
Вы можете ознакомиться с изменениями, внесенными в стартовый шаблон Medusa Next.js Starter Template, в директории Copy to clipboardexamples/medusa-storefront
.
Полный код интеграции можно посмотреть в разделе сomparison page, откройте вкладку Copy to clipboardFiles changed
и изучите различия в каталоге Copy to clipboardexamples/payment-tkassa/medusa-storefront
. Или запустите Copy to clipboarddiff
в терминале:
123git clone https://github.com/gorgojs/medusa-pluginscd medusa-pluginsgit diff @gorgo/medusa-payment-tkassa@0.0.1...main -- examples/payment-tkassa/medusa-storefront
Настройка вебхуков
Чтобы корректно обрабатывать платёжные уведомления от T-Kassa, настройте вебхуки в своём аккаунте T-Business следующим образом:
- Перейдите в раздел Copy to clipboard
Интернет-эквайринг
→ Copy to clipboardМагазины
→ Выберите свой магазин → Copy to clipboardТерминалы
→ Выберите Copy to clipboardТестовый
или Copy to clipboardРабочий
терминал → Нажмите Copy to clipboardНастройки
, чтобы открыть окно настроек. - Установите отправку уведомлений Copy to clipboard
По протоколу HTTP
. - Укажите URL вида: Замените Copy to clipboard
{YOUR_MEDUSA_DOMAIN}
на домен вашей витрины Medusa.
1https://{YOUR_MEDUSA_DOMAIN}/hooks/payment/tkassa_tkassa
Внимание! T-Kassa ожидает сообщение Copy to clipboardOK
в ответе, чтобы подтвердить успешную обработку вебхука и избежать повторных уведомлений. В настоящее время Medusa не поддерживает кастомные ответные сообщения вебхуков «из коробки», но сами вебхуки обрабатываются корректно и без этого. Подробнее см. связанное обсуждение.
Разработка
Документацию по развертыванию окружения для разработки можно найти здесь.
Лицензия
Распространяется на условиях лицензии MIT.