Перейти к содержимому

Matching

Matching — сценарий, в котором вы заранее объявляете спрос на выплату, а платформа закрывает его входящими платежами. Вместо того чтобы выводить средства и отдельно принимать их обратно, вы сводите встречные потоки внутри платформы.

С точки зрения интеграции это не новый API, а режим работы уже знакомых методов POST /payment/pay-out и POST /payment/pay-in.

  1. Вы создаёте заявку — POST /payment/pay-out с флагом isMatching: true.
  2. Заявка ждёт встречные платежи в состоянии «открыта».
  3. Ваши клиенты создают invoice-платежи — POST /payment/pay-in с методом c2c_invoice или sbp_invoice. Платформа сама связывает их с подходящей заявкой.
  4. Клиент подтверждает оплату на платёжной странице, загрузив чек.
  5. Когда сумма набрана, заявка закрывается, и вы получаете уведомление с category: "matching".

Если набрать сумму не удалось, платформа сама создаёт обычную выплату на остаток.

POST /payment/pay-out HTTP/1.1
Host: https://svc.cashwell.io
Content-Type: application/json
X-Secure-Key: <ваш API-ключ>
{
"amount": 15000,
"merchantTransactionId": "txn_matching_001",
"matchingTransactionId": "matching_001",
"isMatching": true,
"callbackUrl": "https://example.com/callback",
"requisite": {
"sbpNumber": "79991234567",
"bank": "SBER",
"ownerName": "Иван Иванов"
}
}
ПолеОбяз.Описание
isMatchingдаtrue — создать заявку вместо обычной выплаты
amountдаСумма спроса
merchantTransactionIdдаВаш идентификатор операции
matchingTransactionIdнетОтдельный идентификатор заявки. Если не передан, используется merchantTransactionId
requisiteдаРеквизиты, на которые уйдёт выплата

Поле method при создании заявки не передаётся — метод вычисляется по реквизиту:

Что передано в requisiteМетод заявки
sbpNumbersbp_invoice
cardNumberc2c_invoice
  • обычная Pay-Out сделка не создаётся;
  • создаётся matching-заявка;
  • в ответ приходит объект в формате выплаты;
  • заявка начинает принимать входящие invoice-платежи.
POST /payment/pay-in HTTP/1.1
Host: https://svc.cashwell.io
Content-Type: application/json
X-Secure-Key: <ваш API-ключ>
{
"amount": 5000,
"method": "sbp_invoice",
"merchantTransactionId": "txn_payin_001",
"payerInfo": {
"ip": "203.0.113.45",
"userId": "usr_847392"
}
}

Связывание выполняется на нашей стороне: платформа ищет открытую заявку вашего кабинета с совместимым методом и, если находит, привязывает платёж к ней.

Метод платежаПодходящие заявки
sbp_invoicesbp, sbp_invoice
c2c_invoicec2c, c2c_invoice

Invoice-платёж не закрывается автоматически: клиент должен подтвердить оплату на платёжной странице, приложив чек. Это два публичных запроса, которые выполняет платёжная страница, а не ваш сервер.

Загрузка чека:

POST /file/trading/pay-in/invoice/upload/public?tradeId={tradeId}

Возвращает uploadMetaKey. Принимается только PDF, до 5 МБ — формат проверяется и по расширению, и по содержимому файла.

Подтверждение:

POST /payment/public/{id}/confirm

В теле передаётся полученный uploadMetaKey. Этот вызов завершает пользовательскую часть сценария и отправляет сделку в дальнейшую обработку.

Если вы используете готовую платёжную страницу по ссылке paymentPageUrl, оба шага выполняются на ней сами — реализовывать их не нужно.

В сценарии два независимых механизма подстраховки.

Заявки не нашлось. Pay-In пришёл с методом c2c_invoice или sbp_invoice, но подходящей открытой заявки нет. Запрос не отклоняется — платформа переводит его в обычный приём платежа:

ЗапрошеноСтанет
sbp_invoicesbp
c2c_invoicec2c

Учитывайте это: метод в ответе может отличаться от метода в запросе.

Заявка не набралась вовремя. Если за отведённое время заявка закрылась не полностью, платформа автоматически создаёт обычную выплату на остаток суммы. Это делает фоновый процесс — отдельный вызов с вашей стороны не нужен.

Состояние заявки приходит на тот же callbackUrl, но отличается от уведомления о сделке:

{
"category": "matching",
"id": "3f1c9a70-3f6b-4a9e-9a10-2b7c4d5e6f70",
"merchantTransactionId": "matching_001",
"matchingTransactionId": "matching_001",
"type": "pay-out",
"status": "success_changed",
"amount": 15000,
"factFiatAmount": 14650,
"crypto": "0",
"rate": 0,
"fee": "0",
"tradeIdsAll": ["...", "..."],
"tradeIdsSuccess": ["..."]
}
ПолеЧто означает
categorymatching — по нему отличайте эти уведомления от уведомлений о сделках
idИдентификатор заявки, не сделки
amountСумма, которую вы заявили
factFiatAmountСумма, фактически закрытая входящими платежами
tradeIdsAllВсе сделки, привязанные к заявке
tradeIdsSuccessТолько те, что закрылись успешно
crypto, rate, feeВсегда нули: заявка — контейнер, а не сделка

Как состояние заявки отображается в status — в разделе Статусы сделок.

Для быстрого прогона сценария есть готовая коллекция:

Она покрывает создание заявки, создание invoice-платежа, отмену, продление таймера, загрузку чека и подтверждение.

Перед запуском заполните переменные:

ПеременнаяЗначение
baseUrlБазовый URL API
secureKeyВаш API-ключ
receiptFileАбсолютный путь к файлу чека на вашей машине
callbackUrlАдрес для проверки webhook, если он нужен

Остальные переменные — matchingId, payInTradeId, publicTradeId, uploadMetaKey — коллекция заполняет сама из ответов предыдущих запросов, поэтому выполнять запросы нужно последовательно сверху вниз.