# Prodamus: Списать деньги по сохранённой карте

Сценарий из mcp-everything. Актуально на 2026-10-12.

Это управляемые вашей системой повторные списания, а не подписка Prodamus. Сначала нужна небольшая реальная оплата, после которой webhook вернёт `binding_id`.

1. Согласуй с поддержкой `sys` и получи отдельный секретный ключ для оплаты по связке.
2. Выполни `GET /?do=link` без `demo_mode`, передав стабильный `client_id` длиной до 32 символов, `sys`, `customer_email`, корзину и подпись ключом платёжной страницы.
3. После успешной первой оплаты прими `POST {urlNotification}` и сохрани пару `client_id` + `binding_id`.
4. Выполни `POST /rest/payment/do/` с этой парой, корзиной, `sys` и подписью отдельным ключом связки. Параметр `do` не передавай.
5. Ответ `{"success":true}` означает только успешную инициацию; окончательный результат возьми из webhook с `payment_init=api`.

```javascript
const { HmacHelper, flattenForm } = require('./hmac/hmac');

const data = {
  products: [{
    name: 'Доступ к обучающим материалам',
    price: '50',
    quantity: '1',
  }],
  client_id: 'customer-4815',
  binding_id: 'TOKEN_FROM_WEBHOOK',
  customer_email: 'customer@example.com',
  customer_phone: '+79998887755',
  urlNotification: 'https://example.com/prodamus/webhook',
  sys: 'your_system',
};

const body = new URLSearchParams(flattenForm(data));
body.append(
  'signature',
  HmacHelper.create(data, process.env.PRODAMUS_BINDING_SECRET_KEY),
);

const response = await fetch(
  'https://YOUR_DOMAIN.payform.ru/rest/payment/do/',
  {
    method: 'POST',
    headers: { 'content-type': 'application/x-www-form-urlencoded;charset=UTF-8' },
    body,
  },
);
const result = await response.json();
if (!response.ok || result.success !== true) {
  throw new Error(result.error ?? `HTTP ${response.status}`);
}
```

## Базовые URL

- Платёжная страница и REST API: `https://<subdomain>.payform.ru`
- Скрипт виджета: `https://widget.prodamus.ru/src/init.js`
- Стили виджета: `https://widget.prodamus.ru/src/init.css`
- Отдельного тестового URL в изученных страницах не указано: `demo_mode=1`

## Авторизация

Тип: Другое

Секретный ключ доступен в настройках платёжной страницы в блоке «Секретный ключ». Для создания платёжных ссылок, управления подписками и вызова `GET или POST /rest/payment/do/` данные запроса без поля `signature` рекурсивно приводят к строкам, сортируют по ключам, преобразуют в JSON, экранируют `/` и подписывают HMAC SHA-256. Готовые реализации `Hmac.php`, `hmac.js`, `prodamus_hmac.py`, `HmacHelper.cs`, `HmacHelper.java` и `hmac.go` опубликованы на страницах документации.

Входящий webhook подписан в заголовке `Sign`; подпись проверяется тем же секретным ключом платёжной страницы. Для оплаты по связке поддержка выдаёт отдельный ключ, привязанный к `sys`; ключ платёжной страницы используют только для первого платежа.

Для `GET /rest/receipt/getReceipts` и `GET /rest/payment-methods/getList` передаются заголовки `Timestamp` и `Authorization: Bearer <token>`, где `<token> = base64_encode(<timestamp> . md5(<SECRET_KEY>))`.

## Методы сценария

### {urlNotification} — Получить webhook об оплате

Prodamus отправляет итоговый статус платежа методом POST. При успешной обработке endpoint должен вернуть `HTTP 200`.

Документация: https://help.prodamus.ru/payform/tekhnicheskaya-dokumentaciya/webhook-ob-oplate

| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
| `Sign` | header | string | да | HMAC-подпись входящего тела |
| `date` | body | string | да | Дата платежа |
| `order_id` | body | number | да | ID заказа в Prodamus |
| `order_num` | body | string | да | Номер заказа на стороне магазина; может быть пустым |
| `sum` | body | string | да | Сумма заказа |
| `currency` | body | string | да | rub, usd или eur |
| `attempt` | body | string | да | Номер попытки доставки |
| `products` | body | array | да | Корзина товаров |
| `products[i].name` | body | string | да | Наименование товара |
| `products[i].price` | body | number | да | Цена за единицу |
| `products[i].quantity` | body | integer | да | Количество |
| `payment_status` | body | string | да | success, order_canceled или order_denied |
| `payment_status_description` | body | string | да | Расшифровка статуса |
| `payment_init` | body | string | да | api, auto или manual |

### GET /?do=link — Создать платёжную ссылку

Endpoint возвращает ссылку при `do=link` или сразу открывает форму при `do=pay`. Запрос также можно отправить методом POST с телом `application/x-www-form-urlencoded` или `multipart/form-data`.

Пример ответа при `do=link`:

Документация: https://help.prodamus.ru/payform/tekhnicheskaya-dokumentaciya/sozdanie-platezhnoy-ssylki#запрос-на-создание-ссылки-/-переход-к-оплате

| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
| `do` | query | string | да | link — вернуть ссылку; pay — перейти к оплате |
| `products` | query | array | нет | Корзина; без неё клиент заполняет товар на странице |
| `products[i].name` | query | string | да | Наименование переданной позиции |
| `products[i].price` | query | number | да | Цена за единицу переданной позиции |
| `products[i].quantity` | query | integer | да | Количество переданной позиции |
| `order_sum` | query | number | нет | Сумма заказа; при do=link без products становится ценой базового товара |
| `order_id` | query | string | нет | Номер заказа в вашей системе |
| `customer_phone` | query | string | нет | Телефон клиента |
| `customer_email` | query | string | нет | Email клиента |
| `sys` | query | string | нет | Код интеграции от поддержки; обязателен для интеграции сервиса |
| `urlNotification` | query | string | нет | URL webhook; учитывается вместе с sys |
| `urlReturn` | query | string | нет | URL возврата без оплаты |
| `urlSuccess` | query | string | нет | URL возврата после успешной оплаты |
| `subscription` | query | integer | нет | ID подписки; если он передан, products игнорируется |
| `demo_mode` | query | integer | нет | Значение 1 включает демо-режим для платежа |
| `callbackType` | query | string | нет | Значение json запрашивает webhook в JSON |
| `signature` | query | string | да | HMAC SHA-256 подпись запроса |

Пример запроса:

```
https://payform.ru/h9brIKu/
```

### POST /rest/payment/do/ — Списать деньги по сохранённой карте

Инициирует платёж по паре `client_id` + `binding_id`. Документация допускает GET или POST; здесь указан POST, использованный в официальных примерах. Запрос подписывается отдельным ключом, который поддержка привязала к `sys`; параметр `do` не передаётся.

Документация: https://help.prodamus.ru/payform/tekhnicheskaya-dokumentaciya/oplata-po-svyazke-cherez-api#шаг-2.-инициируйте-автоплатёж

| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
| `products` | body | array | да | Корзина списания |
| `products[i].name` | body | string | да | Наименование позиции |
| `products[i].price` | body | string | да | Цена позиции |
| `products[i].quantity` | body | string | да | Количество |
| `client_id` | body | string | да | Стабильный ID покупателя, до 32 символов |
| `binding_id` | body | string | да | Токен карты из webhook первого платежа |
| `customer_email` | body | string | да | Email покупателя |
| `customer_phone` | body | string | нет | Телефон покупателя |
| `urlNotification` | body | string | нет | HTTPS URL webhook |
| `sys` | body | string | да | Согласованный с поддержкой код интеграции |
| `signature` | body | string | да | HMAC SHA-256 подпись отдельным ключом связки |

Пример ответа:

```json
{"success":true}
```

## Нюансы

- `urlSuccess` и клиентские редиректы не подтверждают поступление денег. Выдавай товар или доступ только после проверенного webhook с `payment_status=success`.
- Подпись запроса считается без поля `signature`; значения приводятся к строкам, ключи сортируются рекурсивно, JSON подписывается HMAC SHA-256 после экранирования `/`.
- Документация webhook называет базовым форматом `application/x-www-form-urlencoded`, а тестовый чек-лист ожидает `multipart/form-data`; для `callbackType=json` приходит `application/json`. Приёмник должен разбирать фактически выбранный формат до проверки `Sign`.
- Повторная доставка webhook допустима: поле `attempt` может увеличиваться. Обработчик должен быть идемпотентным и отвечать `HTTP 200` только после успешной обработки.
- При `subscription` корзина `products` игнорируется. После деактивации подписки от лица пользователя повторная активация невозможна; нужно оформить подписку заново.
- Оплата по связке не поддерживает тестовый режим. Для первого платежа нужен ключ страницы, для `/rest/payment/do/` — отдельный ключ от поддержки, привязанный к `sys`.
- Синхронный `{"success":true}` от `/rest/payment/do/` подтверждает только инициацию. Итог проверяется по webhook с `payment_init=api`.
- Для `GET /rest/payment-methods/getList` `Timestamp` может быть любой непустой строкой: сервер не проверяет формат или актуальность, срок запроса не ограничен и защиты от повторного воспроизведения нет.
- Тело ответа платёжной формы всегда в UTF-8, но `Content-Type` объявляет `charset=WINDOWS-1251`; это отдельно отмечено в примерах C#.
- Статусы `postMessage` гарантированно доступны для карт РФ, СБП и Сбербанк-онлайн. Для других способов оплаты используй webhook.
- Если `available_payment_methods` отфильтровал все способы, параметр игнорируется и показывается полный список; если пустой результат дал `available_payment_method_groups`, форма показывает ошибку об отсутствии методов.
- В демо-платежах защитное изменение подписи применяется только когда боевой режим формы отключил менеджер Prodamus; пользовательский демо-режим в настройках страницы на подпись не влияет.

## Другие сценарии

- [Принять разовую оплату по ссылке](https://mcp-everything.ru/integrations/prodamus/scenarios/prinyat-razovuyu-oplatu-po-ssylke.md)
- [Надёжно обработать webhook об оплате](https://mcp-everything.ru/integrations/prodamus/scenarios/nadezhno-obrabotat-webhook-ob-oplate.md)
- [Принять оплату во встроенном виджете](https://mcp-everything.ru/integrations/prodamus/scenarios/prinyat-oplatu-vo-vstroennom-vidzhete.md)
- [Создать и остановить подписку](https://mcp-everything.ru/integrations/prodamus/scenarios/sozdat-i-ostanovit-podpisku.md)
- [Получить фискальные чеки заказа](https://mcp-everything.ru/integrations/prodamus/scenarios/poluchit-fiskalnye-cheki-zakaza.md)

---

Если этого недостаточно — официальная документация: https://help.prodamus.ru/payform/tekhnicheskaya-dokumentaciya
Вся интеграция одним документом: https://mcp-everything.ru/integrations/prodamus.md
