Как подключить Payme к сайту: руководство для разработчика
Практика4 минРедакция Innovialabs
Коротко
Payme сам вызывает ваш сервер по протоколу JSON-RPC: вы реализуете шесть методов Merchant API, проверяете авторизацию и сумму в тийинах, храните транзакции с состояниями 1, 2, -1, -2 и проходите все сценарии в песочнице до перехода на боевой ключ.
Короткий ответ
Интеграция Payme устроена «наоборот»: не ваш сайт опрашивает Payme, а Payme вызывает ваш endpoint и спрашивает, можно ли принять платеж, создает транзакцию, проводит и при необходимости отменяет ее. Вам нужно:
- Зарегистрироваться как мерчант и создать кассу.
- Реализовать методы Merchant API на своем сервере.
- Отправлять клиента на страницу оплаты Payme со ссылкой на заказ.
- Пройти тесты в песочнице и переключиться на боевой ключ.
Регистрация мерчанта
- Зарегистрируйте бизнес в кабинете Payme Business и заключите договор.
- Создайте кассу для сайта. Вы получите ID кассы (merchant ID), тестовый ключ и боевой ключ.
- Укажите в настройках кассы URL вашего endpoint и поле счета, по которому Payme будет искать заказ, например
order_id.
Ключи храните в переменных окружения, не в репозитории.
Как Payme вызывает ваш сервер
Каждый вызов — POST-запрос JSON-RPC 2.0 с заголовком Authorization: Basic ..., где закодировано Paycom:<ключ кассы>. Отвечать нужно всегда с HTTP 200, а ошибку передавать в теле ответа.
function isPaymeAuthorized(header: string | null, key: string): boolean {
if (!header?.startsWith("Basic ")) return false;
const decoded = Buffer.from(header.slice(6), "base64").toString();
const sep = decoded.indexOf(":");
return decoded.slice(0, sep) === "Paycom" && decoded.slice(sep + 1) === key;
}
При неверной авторизации возвращайте ошибку -32504.
Методы Merchant API
| Метод | Что делает ваш сервер |
|---|---|
CheckPerformTransaction | Проверяет, что заказ существует, не оплачен и сумма совпадает |
CreateTransaction | Создает транзакцию в состоянии 1 или возвращает уже созданную с тем же id |
PerformTransaction | Проводит транзакцию: состояние 2, заказ оплачен |
CancelTransaction | Отменяет транзакцию: состояние -1 или -2 |
CheckTransaction | Возвращает текущее состояние и время событий |
GetStatement | Отдает список транзакций за период для сверки |
Суммы приходят в тийинах, время — в миллисекундах.
Состояния транзакции
- 1 — создана, ожидает проведения.
- 2 — проведена, деньги списаны, заказ можно выполнять.
- -1 — отменена до проведения.
- -2 — отменена после проведения (возврат).
Храните в своей таблице: ID транзакции Payme, ID заказа, сумму, состояние, create_time, perform_time, cancel_time и причину отмены. Все ответы методов строятся из этих полей.
Ключевые правила обработки
- Идемпотентность. Повторный
CreateTransactionилиPerformTransactionс тем жеidдолжен вернуть тот же результат, а не создавать новую запись. - Один заказ — одна активная транзакция. Если для заказа уже есть транзакция в состоянии 1, новую с другим
idотклоняйте ошибкой из диапазона счета. - Таймаут. Транзакция, которую не провели за отведенное в документации время, отменяется, а
PerformTransactionпо ней возвращает ошибку. - Отмена после проведения разрешена, только если ваш бизнес-процесс допускает возврат. Если товар уже нельзя вернуть, отвечайте ошибкой невозможности отмены.
- Фискальные данные. Если касса требует фискализации, передавайте позиции чека с кодами ИКПУ в формате из документации.
Ссылка на оплату
Клиента отправляют на страницу оплаты Payme. В ссылку кодируются ID кассы, поле счета и сумма в тийинах, а также, по желанию, URL возврата. Важно: возврат клиента на сайт не подтверждает оплату. Статус «оплачен» ставится только в PerformTransaction.
Тестирование в песочнице
У Payme есть песочница, где вы указываете URL своего endpoint и тестовый ключ и прогоняете сценарии: неверная авторизация, несуществующий заказ, неверная сумма, создание, проведение, отмена до и после проведения, повторные вызовы. Боевой ключ подключайте только после того, как все сценарии проходят.
Подробная спецификация — в документации Payme для разработчиков.
Типичные ошибки интеграции
- Сумма в сумах вместо тийинов: проверка суммы падает на каждом заказе.
- Ответ с HTTP 401 или 500 вместо HTTP 200 с объектом ошибки.
- Новая запись при повторном
CreateTransactionвместо возврата существующей. - Заказ помечается оплаченным на
CreateTransaction, а не наPerformTransaction. - Время в секундах вместо миллисекунд.
- Тестовый ключ в продакшене после запуска.