Безопасность
Эта страница — для продавца, который хочет понять, чему можно доверять, и для разработчика, который хочет понять, что именно проверяет код перед тем, как считать заказ оплаченным.
Приватные ключи не запрашиваются никогда
Ни один компонент SolanaPay-KZ — ни плагин WooCommerce, ни сервер для
Tilda, ни библиотека @solanapaykz/core — не создаёт, не хранит и не
запрашивает приватный ключ или мнемоническую фразу. Ни продавца, ни
покупателя.
Это не обещание, а следствие того, как устроен приём платежа. Всё, что
нужно системе для приёма денег — публичный адрес кошелька продавца (тот же,
что вы дали бы, чтобы вам перевели деньги обычным переводом) и случайная
метка (reference) для поиска платежа в блокчейне — 32 случайных байта,
отформатированные как Solana-адрес, для которых пара ключей вообще не
генерируется и не существует. Ни для получения денег, ни для проверки их
поступления подписывать что-либо от чьего-либо имени не требуется — а раз
не требуется, значит, приватный ключ и негде было бы использовать.
Деньги идут напрямую
Перевод происходит с кошелька покупателя на кошелёк продавца одной транзакцией в блокчейне Solana. Ни этот проект, ни его код, ни сервер для Tilda не стоят между ними как получатель или посредник по деньгам — они не могут принять платёж на свой адрес вместо продавца, задержать его или перенаправить. Роль кода везде одна и та же: посчитать сумму по курсу, показать покупателю QR-код и проверить постфактум, что перевод, который уже случился в блокчейне, соответствует заказу.
Что именно проверяется в транзакции
Когда код ищет платёж по метке (reference) и решает, засчитывать ли его,
проверяются пять вещей одновременно:
| Проверяется | Зачем |
|---|---|
| Получатель | перевод должен идти на адрес продавца, зафиксированный в заказе, — иначе это чужой платёж, случайно попавший под ту же метку |
| Сумма | переведено должно быть не меньше суммы из котировки (переплата проходит проверку, недоплата — нет) |
| Монета | перевод должен быть в том токене, что указан в заказе (USDC или SOL) — платёж в другом токене не принимается как оплата этого заказа |
| Метка (reference) | именно по ней транзакция вообще находится среди всех переводов в блокчейне — без метки не с чем сверять получателя, сумму и монету |
Отсутствие ошибки в транзакции (meta.err === null) |
Solana записывает в блокчейн и неудачные транзакции — само наличие записи ещё не значит, что перевод состоялся |
Уровень подтверждения finalized |
самый надёжный из доступных в Solana; более быстрые, но менее надёжные уровни (confirmed, processed) намеренно не используются, потому что для необратимого решения «заказ оплачен» скорость дешевле надёжности не бывает |
Сама сверка делегирована библиотеке @solana/pay (validateTransfer), а не
написана заново: самописная проверка входящей транзакции — то место, где
легче всего по ошибке принять чужой или неполный платёж.
Почему несовпадение суммы не отменяет заказ автоматически
Если транзакция с нужной меткой нашлась, но не прошла проверку — не тот получатель, не тот токен или сумма меньше ожидаемой — система не считает заказ автоматически неоплаченным и не отменяет его. Это состояние, которое требует решения человека: транзакция уже существует в блокчейне, деньги уже могли уйти со счёта покупателя, и это не то же самое, что «покупатель не платил».
Почему сбой сети не меняет состояние
Если узел Solana не отвечает — таймаут, лимит запросов, недоступность — это пробрасывается как ошибка, а не как результат проверки платежа. Заказ остаётся в прежнем состоянии. Молчание сети не является ответом «денег нет»: если бы недоступность узла интерпретировалась как «платежа нет», при перегруженном или временно отключённом RPC-провайдере заказы отменялись бы за реальные, уже отправленные деньги.
По той же причине курс, который не удалось получить ни от одного источника, не приводит к продаже по устаревшему или выдуманному значению — заказ просто не создаётся. Продать по неизвестному курсу хуже, чем не продать.
Что делать продавцу при спорном платеже
- Найдите транзакцию по подписи (
signature), которая сохраняется в заметке заказа (WooCommerce) или в списке заказов (/adminдля сервера Tilda). - Посмотрите её в публичном блок-эксплорере Solana или через сам RPC — получателя, сумму и токен можно проверить независимо от того, что решил код.
- Решите по фактическому содержимому транзакции: засчитать оплату, запросить доплату у покупателя или вернуть ему деньги напрямую со своего кошелька, если перевод пришёл, а заказ по каким-то причинам не актуален.
Это решение всегда принимает продавец — ни один компонент проекта не может принять его автоматически, потому что для этого ему пришлось бы либо держать деньги (чего он не делает), либо ошибаться на необратимых переводах.
Чего проект не делает
SolanaPay-KZ не берёт на себя роль платёжного посредника — только роль кассира, который считает и проверяет:
- Не оформляет возвраты. Вернуть деньги покупателю может только сам продавец, переводом со своего кошелька, — ни у кого другого нет к этому кошельку доступа.
- Не разрешает споры. Если платёж не сошёлся или пришёл поздно, решение — за продавцом, а не за автоматикой и не за проектом (см. выше).
- Не хранит средства. Ни на одном шаге деньги не проходят через адрес, контролируемый проектом, — только напрямую от покупателя к продавцу.
- Не хранит и не может восстановить приватные ключи — потому что никогда их и не получает.
Если что-то из перечисленного нужно — это отдельная задача продавца или стороннего сервиса, не эта система.