Отмена платежа
Отменяйте платёж, когда заказа больше нет — плательщик ушёл, корзина изменилась, — а оплаты ещё не было.
#!/usr/bin/env bash# Cancel a payment nobody paid yet. The body is empty and signed as such.set -euo pipefail. "$(dirname "$0")/../signed-request.sh"
payment_id=$(mka_required PAYMENT_ID)mka_request POST "/v1/payments/$payment_id/cancel" "" "$(mka_new_key)"// Cancel a payment nobody paid yet. The body is empty and signed as such.import { newKey, print, request, required } from "../signed-request.mjs";
const paymentId = required("PAYMENT_ID");const answer = await request("POST", `/v1/payments/${paymentId}/cancel`, { idempotencyKey: newKey(),});print(answer);<?php// Cancel a payment nobody paid yet. The body is empty and signed as such.
declare(strict_types=1);
require __DIR__ . '/../signed_request.php';
$paymentId = mka_required('PAYMENT_ID');mka_show(mka_request( 'POST', "/v1/payments/{$paymentId}/cancel", null, mka_new_key(),));"""Cancel a payment nobody paid yet. The body is empty and signed as such."""from signed_request import new_key, request, required, show
payment_id = required("PAYMENT_ID")show(request( "POST", f"/v1/payments/{payment_id}/cancel", idempotency_key=new_key(),))//go:build ignore
// Cancel a payment nobody paid yet. The body is empty and signed as such.package main
import ( "docs.processing.yolotech.cc/examples/signedrequest")
func main() { paymentID := signedrequest.Required("PAYMENT_ID") signedrequest.Show(signedrequest.Request("POST", "/v1/payments/"+paymentID+"/cancel", nil, signedrequest.NewKey()))}Тело пустое и подписывается как пустое. Ответ — 202 Accepted, а не «отменён»: реквизиты могут быть уже
открыты в банковском приложении плательщика. В платеже появляется cancellation {id, status}:
cancellation.status |
Значение |
|---|---|
requested, processing |
Провайдер отзывает реквизиты. Платёж в статусе processing. |
succeeded |
Отменён. Платёж в статусе cancelled, и об этом приходит вебхук. |
rejected |
Поздно: деньги пришли раньше. Платёж идёт дальше к succeeded; если нужно, сделайте возврат. |
Чтобы узнать исход, прочитайте платёж или дождитесь его вебхука.
| Ответ | Причина | Что делать |
|---|---|---|
409 payment_busy + Retry-After: 1 |
Реквизиты назначаются прямо сейчас. | Повторите через секунду с тем же Idempotency-Key. |
409 payment_not_cancellable |
Оплачен, завершён или на проверке. | Прочитайте платёж. Оплаченный верните возвратом. |
404 payment_not_found |
Это не ваш платёж. | Проверьте id. |
Повтор с тем же ключом возвращает текущее состояние отмены и никогда не создаёт вторую отмену.
Вместо отмены — исправьте сумму
Заголовок раздела «Вместо отмены — исправьте сумму»Пока плательщик не заплатил и окно открыто, измените сумму на тех же реквизитах, а не отменяйте платёж и не создавайте новый:
#!/usr/bin/env bash# Change the amount the payer is to transfer while the window is open.set -euo pipefail. "$(dirname "$0")/../signed-request.sh"
payment_id=$(mka_required PAYMENT_ID)body=$(cat <<JSON{ "amount": "${AMOUNT:-2600.00}", "currency": "LKR", "payment_version": $(mka_required PAYMENT_VERSION)}JSON)mka_request POST "/v1/payments/$payment_id/amount-correction" "$body" "$(mka_new_key)"// Change the amount the payer is to transfer while the window is open.import { newKey, print, request, required } from "../signed-request.mjs";
const paymentId = required("PAYMENT_ID");const answer = await request("POST", `/v1/payments/${paymentId}/amount-correction`, { body: { amount: process.env.AMOUNT ?? "2600.00", currency: "LKR", payment_version: Number(required("PAYMENT_VERSION")), }, idempotencyKey: newKey(),});print(answer);<?php// Change the amount the payer is to transfer while the window is open.
declare(strict_types=1);
require __DIR__ . '/../signed_request.php';
$paymentId = mka_required('PAYMENT_ID');mka_show(mka_request( 'POST', "/v1/payments/{$paymentId}/amount-correction", [ 'amount' => getenv('AMOUNT') ?: '2600.00', 'currency' => 'LKR', 'payment_version' => (int) mka_required('PAYMENT_VERSION'), ], mka_new_key(),));"""Change the amount the payer is to transfer while the window is open."""import os
from signed_request import new_key, request, required, show
payment_id = required("PAYMENT_ID")show(request( "POST", f"/v1/payments/{payment_id}/amount-correction", body={ "amount": os.environ.get("AMOUNT", "2600.00"), "currency": "LKR", "payment_version": int(required("PAYMENT_VERSION")), }, idempotency_key=new_key(),))//go:build ignore
// Change the amount the payer is to transfer while the window is open.package main
import ( "strconv"
"docs.processing.yolotech.cc/examples/signedrequest")
func main() { paymentID := signedrequest.Required("PAYMENT_ID") version, err := strconv.Atoi(signedrequest.Required("PAYMENT_VERSION")) if err != nil { panic(err) } signedrequest.Show(signedrequest.Request("POST", "/v1/payments/"+paymentID+"/amount-correction", map[string]any{ "amount": signedrequest.Env("AMOUNT", "2600.00"), "currency": "LKR", "payment_version": version, }, signedrequest.NewKey()))}Отправьте payment_version, который вы видели. Ответ — 202 с correction {id, status}; когда исправление
применено, платёж переходит на следующую версию с новой суммой. Устаревшая версия — это
409 payment_version_conflict, платёж, который больше не ждёт денег, — 409 payment_not_correctable,
та же сумма — 409 amount_unchanged.