Tkassa
T-Kassa payment provider for Medusa
Возможности
- 🔗 Бесшовная интеграция с платёжной системой 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 – зарегистрируйтесь или войдите
Установка
yarn add @gorgo/medusa-payment-tkassa# илиnpm install @gorgo/medusa-payment-tkassa
Настройка
Добавьте конфигурацию провайдера в файл в приложении Medusa Admin:
// ...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"},}]}}]})
Добавьте переменные окружения и из личного кабинета T-Business:
Параметры провайдера
Параметр | Описание | Обязательный | По умолчанию |
---|---|---|---|
Ключ терминала, предоставленный T-Kassa (обязателен для аутентификации) | Да | - | |
Пароль для подписи запросов (обязателен для аутентификации) | Да | - | |
Определяет тип проведения платежа:- — одностадийная оплата ( в API)- — двухстадийная оплата ( в API) | Нет | ||
Включает формирование онлайн-чеков по 54-ФЗ | Нет | ||
Версия ФФД: или Применимо только при | Нет | - | |
Система налогообложения:- — общая СН- — упрощенная СН (доходы)- — упрощенная СН (доходы минус расходы)- — единый сельскохозяйственный налог- — патентная СНПрименимо только при | Нет | - | |
Ставка НДС по товарам:- — без НДС- — 0%- — 5%- — 7%- — 10%- — 20%- — 5/105- — 7/107- — 10/110- — 20/120Применимо только при | Нет | - | |
Ставка НДС для доставки (аналогично )Применимо только при | Нет | - |
Интеграция с Storefront (витриной магазина)
Для интеграции платёжного провайдера T-Kassa с storefront на Next.js начните с добавления необходимых UI-компонентов. Таким образом провайдер будет отображаться на странице оформления заказа наряду с другими доступными методами оплаты.
Когда пользователь выбирает T-Kassa, витрина должна вызвать метод с нужными параметрами. Это создаст платёжную сессию через API T-Kassa и подготовит покупателя к перенаправлению. После этого кнопка Place Order должна отправить пользователя на страницу оплаты T-Kassa, где он сможет выбрать предпочтительный способ оплаты.
После завершения оплаты T-Kassa одновременно отправит вебхук и перенаправит покупателя обратно в витрину. То событие, которое придёт первым, завершит корзину и создаст новый заказ в Medusa.
Для запуска на Next.js необходимо внести следующие изменения:
1. Конфигурация платежного провайдера
Чтобы сделать T-Kassa доступным в качестве способа оплаты на странице оформления заказа витрины магазина, необходимо добавить её конфигурацию в маппинг платёжных провайдеров в файле с константами вашего storefront. Этот маппинг определяет как каждый провайдер отображается в интерфейсе.
Откройте и добавьте следующий код:
export 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")}
Вы расширяете объект , добавляя в него запись . Эта запись определяет заголовок и иконку, которые будут отображаться для T-Kassa на странице оформления заказа.
Вспомогательная функция проверяет, принадлежит ли переданный к T-Kassa. Это используется при рендеринге UI-компонентов, специфичных для конкретного провайдера.
2. Настройки Сookie
При подключении T-Kassa настройте политику cookie так, чтобы поддерживались междоменные редиректы. Это нужно для сохранения платёжной сессии при возврате пользователя в магазин.
Откройте и обновите конфигурацию файлов cookie следующим образом:
export const setCartId = async (cartId: string) => {cookies.set("_medusa_cart_id", cartId, {// ... другие настройки cookiesameSite: "lax", // Переключено с режима «Strict» для междоменных редиректов})}
Эта вспомогательная функция сохраняет идентификатор корзины в cookie с именем .
Опция установлена в значение вместо . Это изменение гарантирует, что cookie будет отправляться при кросс-доменных запросах во время процесса редиректа через T-Kassa, предотвращая потерю платёжной сессии.
3. Инициализация платёжной сессии
Чтобы перенаправить покупателя в T-Kassa, платёжная сессия должна быть корректно инициализирована с обязательными параметрами, включая return URL для обоих случаев: успешной и неуспешной оплаты.
Откройте и обновите логику инициализации платежа, включив в нее данные корзины и URL возврата для T-Kassa:
await 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 параметры и определяют, куда будет перенаправлен покупатель после попытки оплаты. Оба URL динамически формируются на основе базового URL storefront, идентификатора корзины и выбранного кода страны.
Объект включается в данные инициализации для формирования чека в соответствии с Федеральным законом № 54.
4. Компонент кнопки оплаты
В storefront для каждого платёжного провайдера необходим отдельный компонент кнопки оплаты. Он отвечает за обработку оформления заказа после подтверждения пользователем и, используя данные платёжного сеанса, перенаправляет его на страницу оплаты T-Kassa.
Откройте и добавьте следующий код:
const 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)}}}
Этот компонент находит для T-Kassa в текущей корзине и извлекает , предоставленный бэкендом. При нажатии кнопки Place order покупатель перенаправляется на этот URL для завершения транзакции на странице оплаты T-Kassa.
Если отсутствует, компонент выводит сообщение об ошибке, не позволяя продолжить. Состояние обеспечивает визуальную обратную связь во время подготовки перенаправления.
Компонент определяет, принадлежит ли текущая платёжная сессия к T-Kassa, с помощью вспомогательной функции . Если да, он рендерит для обработки процесса оплаты.
Интеграция этого компонента гарантирует, что процесс оплаты через T-Kassa будет запускаться при оформлении заказа.
5. API-роут подтверждения платежа
После того как покупатель завершает оплату на странице T-Kassa, он перенаправляется обратно на витрину магазина. Необходимо создать API-роут, который обработает этот callback, проверит статус платежа и завершит корзину.
Создайте файл со следующим содержимым:
import { 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()) }// Получить актуальные значения корзиныconst cartCacheTag = await getCacheTag("carts")revalidateTag(cartCacheTag)const { cart } = await sdk.store.cart.retrieve(cartId, {fields: "id, order_link.order_id"},headers)if (!cart) {return NextResponse.redirect(`${origin}/${countryCode}`)}const orderId = (cart as unknown as Record<string, any>).order_link?.order_idif (!orderId) {await placeOrder(cartId)// Ошибка при неавторизованном платежеreturn NextResponse.redirect(`${origin}/${countryCode}/checkout?step=review&error=payment_failed`)}const orderCacheTag = await getCacheTag("orders")revalidateTag(orderCacheTag)removeCartId()return NextResponse.redirect(`${origin}/${countryCode}/order/${orderId}/confirmed`)}
Этот API-роут обрабатывает редирект от T-Kassa после попытки оплаты. Он получает актуальное состояние корзины, чтобы убедиться, что все изменения, внесённые во время оплаты, были отражены.
Если в корзине нет связанного идентификатора заказа, обработчик роута пытается оформить заказ. В случае успеха покупатель перенаправляется на страницу подтверждения заказа. Если же при обработке корзины возникла ошибка, покупатель возвращается на страницу оформления заказа с указанием ошибки и может повторить процесс оплаты заказа.
Когда оплата проходит успешно, роут повторно валидирует кэшированные данные корзины и заказа, удаляет cookie корзины и перенаправляет покупателя на страницу подтверждения заказа. Это гарантирует корректное завершение платёжного процесса и сохранение актуальных данных в storefront.
Пример
Вы можете ознакомиться с изменениями, внесенными в стартовый шаблон Medusa Next.js Starter Template, в директории .
Полный код интеграции можно посмотреть в разделе сomparison page, откройте вкладку и изучите различия в каталоге . Или запустите в терминале:
git 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 следующим образом:
-
Перейдите в раздел → → Выберите свой магазин → → Выберите или терминал → Нажмите , чтобы открыть окно настроек.
-
Установите отправку уведомлений .
-
Укажите URL вида:
Замените на домен вашей витрины Medusa.
Внимание! T-Kassa ожидает сообщение в ответе, чтобы подтвердить успешную обработку вебхука и избежать повторных уведомлений. В настоящее время Medusa не поддерживает кастомные ответные сообщения вебхуков «из коробки», но сами вебхуки обрабатываются корректно и без этого. Подробнее см. связанное обсуждение.
Разработка
Документацию по развертыванию окружения для разработки можно найти здесь.
Лицензия
Распространяется на условиях лицензии MIT.