protopaysAPI

Апелляция по платежу

Если платёж в failed, можно открыть спор: текст причины и файл (чек). Окно ~24 часа после смены статуса. payment в URL — числовой id платежа.

POSThttps://api.protopays.io/api/v1/payments/{payment}/appeal

Заголовки ключа — как в аутентификации, но подпись не от сырого multipart.

Подпись

HMAC-SHA256 от такой строки (UTF-8, перевод строки LF):

code
appeal-v1
{reason}
{originalFileName}
{sizeBytes}

sizeBytes — размер файла в байтах. Результат — hex в нижнем регистре в Signature.

Поля

ПолеТипОбяз.Описание
reasonstringдаПричина, до 10000 символов.
filefileдаPDF / JPEG / PNG / WEBP / DOC / DOCX.

Пример

node
import crypto from "node:crypto";
import fs from "node:fs";

const secret = "<SECRET>";
const paymentId = 1001;
const reason = "Клиент оплатил, статус failed ошибочно";
const filePath = "./receipt.pdf";
const buf = fs.readFileSync(filePath);
const originalName = "receipt.pdf";
const sizeBytes = String(buf.length);

const canonical = `appeal-v1\n${reason}\n${originalName}\n${sizeBytes}`;
const signature = crypto.createHmac("sha256", secret).update(canonical, "utf8").digest("hex");

const form = new FormData();
form.append("reason", reason);
form.append("file", new File([buf], originalName, { type: "application/pdf" }));

const res = await fetch(`https://api.protopays.io/api/v1/payments/${paymentId}/appeal`, {
  method: "POST",
  headers: {
    "X-Merchant-Key-Id": "<KEY_ID>",
    "X-Merchant-Secret": secret,
    Signature: signature,
  },
  body: form,
});
console.log(res.status, await res.text());

Ответ 201

json
{
  "message": "Appeal opened",
  "data": {
    "appealId": 1,
    "paymentId": 1001,
    "paymentStatus": "appeal",
    "appealStatus": "open"
  }
}

Ошибки

  • 403 — ключ не подходит
  • 409 — спор уже открыт
  • 422 — не failed / срок вышел / нет исполнителя