Матчинг: перевод с чеком¶
Матчинг (иногда пишут «метчинг», англ. matching) — перевод на карту или по СБП, который
провайдер зачисляет только по чеку плательщика. Плательщик переводит на выданные
реквизиты, вы присылаете файл чека, провайдер сверяет его с поступлением и подтверждает
оплату. Заявка устроена так же, как приём по карте и приём по СБП: тот же
запрос, те же статусы, callback-и и правила повторов. Отличаются payment_method и шаг с чеком.
| Перевод на карту | Перевод на карту (матчинг) | СБП | СБП (матчинг) | |
|---|---|---|---|---|
payment_method |
card_transfer |
card_matching |
sbp |
sbp_matching |
| Что получает плательщик | номер карты | номер карты | номер телефона | номер телефона |
| Чек после перевода | не нужен | нужен | не нужен | нужен |
Методы матчинга — отдельные методы договора: у них свои условия, подключает их менеджер.
Метод, которого нет в договоре проекта, — 422 payment_not_covered.
Как проходит оплата¶
- Ваш сервер → API
POST /api/v1/paymentsсpayment_method=card_matchingилиsbp_matching - API ⇢ Ваш сервер
201:status=processing,requisite,holder_name - Ваш сервер → ПлательщикРеквизиты, сумма, срок и просьба приложить чек
- ПлательщикПереводит и сохраняет чек (PDF или скриншот из приложения банка)
- Ваш сервер → API
POST /api/v1/payments/{id}/receiptс файлом чека - API ⇢ Ваш сервер
201: чек принят,status=pending - APIПередаёт чек провайдеру, провайдер сверяет оплату
- API → Ваш серверCallback:
completedилиcanceled
Чек не меняет ни статус, ни сумму заявки: итог приходит обычным callback-ом.
Без чека провайдер отменит заявку по сроку — придёт callback canceled.
Создать заявку¶
POST /api/v1/payments с payment_method: "card_matching" или "sbp_matching". Запрос
подписывается так же, как для СБП, поля — те же, см.
Приём по СБП → Поля запроса.
Ответ 201 Created — такой же, как у перевода на карту (у sbp_matching —
как у СБП):
{
"id": "3f1c2b9e-6a8d-4c4b-9a71-2c7f5d1e0a42",
"merchant_payment_id": "order-1005",
"status": "processing",
"amount": 5000,
"initial_amount": 5000,
"currency": "RUB",
"geo_code": "RU",
"payment_method": "card_matching",
"bank_code": null,
"is_intrabank": false,
"requisite": "2200123456789010",
"requisite_bank": "Сбер",
"holder_name": "Мария П.",
"created_at": "2026-10-23T09:30:00Z",
"updated_at": "2026-10-23T09:30:01Z"
}
requisite— номер карты (card_matching) или номер телефона (sbp_matching);holder_name,requisite_bank— получатель и его банк;id— понадобится для загрузки чека.
Что показать плательщику¶
Всё, что для карты или СБП: реквизит с кнопкой
«Скопировать», получатель, ровно amount и обратный отсчёт срока. Дополнительно:
- Загрузка чека. После перевода попросите плательщика приложить чек — PDF или скриншот из приложения банка, где видны сумма, дата и получатель.
- Предупреждение. Без чека оплата не будет зачислена, а заявка отменится по сроку.
Прислать чек¶
POST {{base_url}}/api/v1/payments/{id}/receipt — загрузка чека заявки. Право токена
payments:create, подпись обязательна всегда.
| Тело | multipart/form-data, ровно одно поле — файл receipt. Других полей нет |
| Файл | JPG, PNG или PDF — тип проверяется по содержимому, а не по расширению |
| Размер | файл до 5 МБ, тело до 5 МБ плюс 64 КБ — независимо от лимита тела проекта |
| Рекомендация | файл не больше 200 КБ: часть провайдеров больший файл не принимает, и такой чек до провайдера не дойдёт |
| Подпись | Content-Digest — SHA-256 точных байтов multipart-тела, как оно уходит в запрос |
| Сколько чеков | один на заявку |
Когда чек принимается:
- метод заявки —
card_matchingилиsbp_matching; - заявка не тестовая (
is_test: false); - заявка в статусе
processing, и реквизиты уже выданы.
POST {{base_url}}/api/v1/payments/3f1c2b9e-6a8d-4c4b-9a71-2c7f5d1e0a42/receipt HTTP/1.1
Authorization: Bearer nl_live_...
Content-Type: multipart/form-data; boundary=receipt-7d1f0c
Content-Digest: sha-256=:…:
X-Request-ID: 6a1e7c3b-2d4f-4b8a-9c0d-1e2f3a4b5c6d
X-Request-Nonce: 2c26b46b68ffc68ff99b453c1d304134
Signature-Input: sig1=(…);created=…;expires=…;keyid="ed25519-…";alg="ed25519"
Signature: sig1=:…:
--receipt-7d1f0c
Content-Disposition: form-data; name="receipt"; filename="чек.pdf"
Content-Type: application/pdf
<байты файла>
--receipt-7d1f0c--
Подписывайте те же байты, что отправляете. Удобнее всего собрать multipart-тело самому, с
известным boundary, посчитать по нему подпись и отправить тело как есть. Пример на Python с
функцией sign_request из готовых функций подписи:
import os
import secrets
import urllib.request
from sign import load_private_key, sign_request
payment_id = "3f1c2b9e-6a8d-4c4b-9a71-2c7f5d1e0a42"
url = os.environ["BASE_URL"].rstrip("/") + f"/api/v1/payments/{payment_id}/receipt"
with open("receipt.pdf", "rb") as f:
content = f.read()
boundary = "receipt-" + secrets.token_hex(8)
body = (
f"--{boundary}\r\n"
'Content-Disposition: form-data; name="receipt"; filename="receipt.pdf"\r\n'
"Content-Type: application/pdf\r\n\r\n"
).encode() + content + f"\r\n--{boundary}--\r\n".encode()
with open(os.environ["SIGNING_KEY_FILE"], "rb") as f:
key = load_private_key(f.read())
headers = sign_request("POST", url, body, key, os.environ["SIGNING_KEY_ID"])
headers["Authorization"] = "Bearer " + os.environ["API_TOKEN"]
headers["Content-Type"] = f"multipart/form-data; boundary={boundary}"
request = urllib.request.Request(url, data=body, headers=headers, method="POST")
with urllib.request.urlopen(request, timeout=30) as response:
print(response.status, response.read().decode())
Ответ¶
201 Created — чек принят и передаётся провайдеру:
{
"payment_id": "3f1c2b9e-6a8d-4c4b-9a71-2c7f5d1e0a42",
"status": "pending",
"file_name": "чек.pdf",
"sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"created_at": "2026-10-23T09:41:00Z"
}
| Поле | Что значит |
|---|---|
payment_id |
id заявки |
status |
доставка чека провайдеру: pending, sent, failed — см. ниже |
file_name |
имя файла; оно очищается, расширение приводится к содержимому |
sha256 |
SHA-256 файла, hex |
created_at |
когда чек принят, UTC |
Повтор безопасен. Тот же файл ещё раз (тот же sha256) — 200 OK с уже принятым чеком.
Если ответа не было (таймаут, обрыв), отправьте тот же файл с новыми nonce и подписью.
Другой файл, когда чек уже есть, — 409 payment_receipt_exists.
Ошибки¶
| HTTP | error |
Когда | Что делать |
|---|---|---|---|
| 400 | invalid_payment_receipt |
Тело не multipart/form-data, нет файла receipt, есть другое поле или поле повторяется |
Исправить запрос |
| 400 | attachment_type_not_allowed |
Файл по содержимому не JPG, PNG и не PDF | Прислать JPG, PNG или PDF |
| 404 | payment_not_found |
Заявки нет, она другого проекта или id не UUID |
Проверить id |
| 409 | payment_receipt_not_allowed |
Чек сейчас не принимается, причина — в reason (таблица ниже) |
По причине |
| 409 | payment_receipt_exists |
У заявки уже есть другой чек | Второй чек не нужен; статус — GET …/receipt |
| 409 | attachment_limit_reached |
У заявки уже 20 файлов | Связаться с поддержкой |
| 409 | request_replayed |
Этот X-Request-Nonce уже был |
Повторить с новым nonce и подписью |
| 413 | request_too_large |
Тело больше 5 МБ плюс 64 КБ или файл больше 5 МБ | Уменьшить файл |
Общие ошибки (401, 403, 429, 500, 503) — как у остальных запросов, см.
Статусы и ошибки.
reason |
Почему |
|---|---|
not_matching_method |
Метод заявки — не card_matching и не sbp_matching: чек не нужен |
test_payment |
Заявка тестовая — чеки к тестовым заявкам не принимаются |
payment_not_processing |
Заявка уже закрыта (не processing) |
requisites_not_issued |
Реквизиты ещё не выданы |
Если заявка уже закрылась canceled, а плательщик оплатил, — это не чек матчинга, а
апелляция: POST /api/v1/payments/{id}/disputes.
Статус чека¶
GET {{base_url}}/api/v1/payments/{id}/receipt — чек заявки и его доставка провайдеру. Право
payments:read; подпись — только если её требует политика проекта (signature_required).
Ответ 200 — тот же объект, что при загрузке. Ошибки: 404 payment_not_found — такой
заявки в проекте нет, 404 payment_receipt_not_found — у заявки нет чека.
Статусы чека¶
status |
Что значит |
|---|---|
pending |
Чек принят, передаём провайдеру (при сбое связи — с повторами) |
sent |
Провайдер принял чек |
failed |
Провайдер не принял чек; сотрудники отправят его ещё раз |
Статус чека — это только доставка файла. Оплачена ли заявка, говорит статус заявки и callback.
Статусы и результат¶
Статусы заявки, callback-и и опрос — такие же, как у СБП: Статусы и Как узнать результат.
- Провайдер подтвердил оплату по чеку — callback
completed. Сумма вamountможет отличаться отinitial_amount, если оплату подтвердили на другую сумму. - Чек не прислали или оплата не подтвердилась до срока — callback
canceled.
Песочница¶
Тестовые заявки (is_test: true) с методами матчинга создаются и закрываются, как в
песочнице: исход задаёт сумма. Чек к тестовой заявке не принимается —
409 payment_receipt_not_allowed с reason: "test_payment". Так можно проверить разбор ошибки
загрузки чека.
Смотрите также¶
- Методы оплаты — все методы и что получает плательщик.
- Приём по карте и Приём по СБП — те же заявки без чека.
- Справочник API —
uploadPaymentReceiptиgetPaymentReceipt.