Интеграция на сайт платежей ЮKassa через api с готовым виджетом оплат и автоплатежами

Как всегда недоволен и буду бросаться какашками. Довелось намедни сравнить интеграции Stripe платежей с ЮКасса, и сделать неприятные выводы:

Stripe — это чётко и ровно

Документация соответствует тому как работает api, как в тестовой так и в продакшн версии. Если вы отладили код интеграции с api и у вас всё работает с тестовыми ключами, то с live ключами всё будет работать на 100% один в один точно так же! В тестовой интеграции вы можете эмулировать любые ситуации и отладить их, в панели всё будет визуализировано как на ладони, любые фильтры, логи и баги вы отловите без проблем.

ЮКасса — это самый популярный в Рунете агрегатор платежей через жопу

Абсолютно всё то, что написано выше о Stripe к ЮКасса не применимо. Поэтому ниже я дам условный код на php для рабочей интеграции. А ещё ниже, я порассуждаю о политике в текущем контексте — почему с IT в РФ всё вот так — через одно место, ну и обосру компанию Яндекс по полной программе. Им всё равно, а мне приятно. Поехали.

Поставим готовую php библиотеку

composer require yoomoney/yookassa-sdk-php

Шаги интеграции:

  1. Получаем confirmation_token для вызова виджета
  2. Вызываем виджет ЮКасса на своей странице
  3. Захватываем либо отменяем платёж
  4. Проводим автоплатежи

Получаем confirmation_token для вызова виджета и payment_id будущего платежа.

При изучении документации и тестировании, не рассчитывайте на то что это будет 100% эмуляция работы. Потом, на продакшене с live ключом внезапно окажется, что там где в доке к апи свойство отмечено как optional, оно по факту required))) Это нормально)

use YooKassa\Client;

$client = new Client();
$client->setAuth(YOOKASSA_SHOP_ID, YOOKASSA_API_SECRET_KEY);

$amount = 111; // сумма платежа

$payment = $client->createPayment(
    [
        'amount' => [
            'value' => $amount, // сумма платежа
            'currency' => 'RUB',
        ],
        'confirmation' => [
            'type' => 'embedded'
        ],
        'capture' => false, // не делаем сразу захват, это на случай например если это условная оплата 1 руб, которую нужно отменить или мы не уверены в доставке товара
        // 'save_payment_method' => true, // если подключены автоплатежи, то можно будет сохранить метод для автоплатежей
        'description' => 'Описание покупки',
        'merchant_customer_id' => 777, // id пользователя в вашей системе
        'receipt' => [ // данные чека, required, хоть в доке отмечены как optional
            'customer' => [
                'email' => '[email protected]'
            ],
            'items' => [
                [
                    'description' => 'Оплата покупки',
                    'amount' => [
                        'value' => number_format($amount, 2, '.', ''),
                        'currency' => 'RUB'
                    ],
                    'vat_code' => 1,
                    'quantity' => '1',
                    'payment_subject' => 'payment',
                    'payment_mode' => 'full_payment'
                ]
            ]
        ]
    ],
    uniqid('', true)
);

$confirmation_token = $payment->getConfirmation()->getConfirmationToken(); // токен для инициализации виджета
$paymentId = $payment->getId(); //  id платежа в ЮКасса

Вызываем виджет ЮКасса на своей странице, встраиваем его в свой элемент.

<script src="https://yookassa.ru/checkout-widget/v1/checkout-widget.js"></script>

<script>
const checkout = new window.YooMoneyCheckoutWidget({
    confirmation_token: '$confirmation_token', // Токен, который перед проведением оплаты нужно получить от ЮKassa
    return_url: 'https://' + location.hostname + '/confirm-page?paymentId=$paymentId',
    error_callback: function(error) {
        //Обработка ошибок инициализации
        console.log(error);
    }
});

checkout.render('payment-element')
    //Метод возвращает Promise, исполнение которого говорит о полной загрузке платежной формы (можно не использовать).
    .then(() => {
        //Код, который нужно выполнить после отображения платежной формы.
    });
</script>

Захватываем либо отменяем платёж

после успешной оплаты юзер попадает на /confirm-page на которую передаем payment_id
на этой странице мы проверяем статус платежа и захватываем, либо отменяем платеж

$paymentId = $_GET['paymentId'];

use YooKassa\Client;

$client = new Client();
$client->setAuth(YOOKASSA_SHOP_ID, YOOKASSA_API_SECRET_KEY);
$payment = $client->getPaymentInfo($paymentId);

if ($payment->getStatus() != 'waiting_for_capture') { // проверем статус платежа
    exit('Ошибка платежа!');
}

// платеж захвачен банком, дальнейшее сделать мы можем и позже, в течении 7 суток(не для всеъх способов оплаты подходит)

$is_delivered = true; // статус доставки нашего товара юзеру

if ($is_delivered) { // если товар доставлен, то захватываем платеж
    $payment = $client->capturePayment(
        [
            'amount' => [
                'value' => intval($payment->amount->value),
                'currency' => 'RUB',
            ],
        ],
        $paymentId,
        uniqid('', true)
    );
    if ($payment->getStatus() != 'succeeded') {
        exit('Ошибка захвата платежа');
    }
} else { // если товар не доставлен, то отменяем платеж
    $payment = $client->cancelPayment(
        $paymentId,
        uniqid('', true)
    );
    if ($payment->getStatus() != 'canceled') {
        exit('Ошибка отмены платежа');
    }
}

// далее, если включены автоплатежи и при создании платежа было задано сохранение его способа save_payment_method = true, то мы можем это проверить и сохранить метод платежа.
// или если клиент сам поставил галочку в виджете

if ($payment && $payment->payment_method && $payment->payment_method->id && $payment->payment_method->saved) {
    $payment_method_id = $payment->payment_method->id; // сохранить метод платежа для автоплатежей
}

Автоплатежи (рекуррентные платежи) ЮКасса

Тут прежде всего стоит разобраться с терминологией. И понять, что именно эти убогие обозвали «автоплатежом». Они назвали автоплатежом платеж по заранее сохраненному способу оплаты(по моему так в stripe это же называется). Но непосредственно реализовывать автоплатежи будете вы. Они не реализованы) Их нет! Есть то что я сказал. Т.е. смотрите, цепочка оплаты выглядит так:

Покупатель => Ваш сервис(вы) => Агрегатор(Юкасса) => Банк

Кто чей клиент в этой цепочке? Так  она и построена. Кто клиент банка получающего оплату? Агрегатор. Кто клиент Агрегатора? Вы. Кто ваш клиент? Покупатель.

Вот для примера достаточно простенький Агрегатор, реализующий реккурентные(авто) платежи для своих клиентов:
https://developers.cloudpayments.ru/#rekurrentnye-platezhi-podpiska

В этом наглядном примере достаточно реализовать лишь 1 оплату, задать период платежей и далее агрегатор проводит платежи сам, лишь присылая вам уведомления на вебхуки.
С этой стороны для агрегатора, в контексте термина автоплатеж, вы — клиент. И это правильно! Ведь именно ВЫ его клиент)

В Юкасса этого нет. Там нет автоплатежей. Вы(или ваш программист) должны будете реализовать своим кодом логику, стеки, периодичность, и лишь потом делать оплаты по сохраненному способу оплаты(payment_method_id). И лишь тогда это станет автоплатежом для вашего клиента.

И вы знаете, в контексте выше и ниже сказанного, я уже даже не вижу ничего удивительного. Знаете что ложится в канву всей логики прям идельно?
Что Юкасса тупо не видит в вас клиента. Она уже на бабки смотрит ВАШИХ клиентов, уже прыгает через вашу голову — по цепочке вас опустили!))) Она уже «автоплатежом» обзывает то, что вы ещё только должны будете реализовать для ВАШЕГО клиента. Это для вашего клиента будет автоплатеж! А для Юкассы это будет всего лишь платеж по заранее сохраненному способу оплаты(payment_method_id), но никак не автоплатеж.

Вы — говно в этой цепочке. Довольны? Не забудьте согласовать с менеджером)))

Для проведения рекуррентных платежей требуется согласование с менеджером. Но если клиент сам поставил галочку в виджете, это поведение не тестировалось на продакшн, по уму и логике вещей, в этом случае $payment->payment_method->saved должен приходить и автоплатеж далее по нему тоже должен аппрувиться.

Но не забывайте что сказано было вначале: ЮКасса — это агрегатор платежей через жопу. Поэтому не надейтесь сильно на логику галочек, и на документацию к их api тоже. Согласуйте с менеджером))))

use YooKassa\Client;

$client = new Client();
$client->setAuth(YOOKASSA_SHOP_ID, YOOKASSA_API_SECRET_KEY);

$amount = 111; // сумма платежа

$payment = $client->createPayment(
    [
        'amount' => [
            'value' => $amount, // сумма платежа
            'currency' => 'RUB',
        ],
        'confirmation' => [
            'type' => 'embedded'
        ],
        'capture' => true, // делаем сразу захват
        'payment_method_id' => $payment_method_id,
        'description' => 'Описание покупки',
        'merchant_customer_id' => 777, // id пользователя в вашей системе
        'receipt' => [ // данные чека, required, хоть в доке отмечены как optional
            'customer' => [
                'email' => '[email protected]'
            ],
            'items' => [
                [
                    'description' => 'Оплата покупки',
                    'amount' => [
                        'value' => number_format($amount, 2, '.', ''),
                        'currency' => 'RUB'
                    ],
                    'vat_code' => 1,
                    'quantity' => '1',
                    'payment_subject' => 'payment',
                    'payment_mode' => 'full_payment'
                ]
            ]
        ]
    ],
    uniqid('', true)
);

$status = $payment->getStatus();
if ($status != 'succeeded') {
    exit('Ошибка платежа');
}

Ну вот так. Кстати когда будете согласовывать что-то там с менджером вопросы, не надейтесь на его квалификацию))) Её нет. Она ушла погулять))) Есть не вникающий балванчик дающий отписки. Он может советовать вам весьма стрёмные решения и реализации, сам того не ведая что творит и говорит. Это нормально)

Почему в Яндексе и вообще с IT РФ всё вот так через сраку?

Почему в российских it сервисах всё вот так работает как в сельском туалете? У любой крупной, уважающей себя компании есть определенные политики(policy), которых они строго придерживаются. А ещё они работают в правовом поле своего государства. В правовом поле какого государства работает Яндекс и какие у него политики? Давайте посмотрим наглядно на примере.

Мы все пользуемся Github.com, возьмем такую американскую компанию например. У нас в Донецкой Народной Республике, не работают некоторые сервисы этой американской компании. Хотите ими воспользоваться как клиент — а они внезапно не работают. И вам выплевывают ссылочку

https://docs.github.com/ru/site-policy/other-site-policies/github-and-trade-controls#what-is-available-and-not-available
Переходим и видим, ага Крым, Донецк, Луганск, санкции, всё ясно. Обидно, досадно, но ладно. Уважающая себя компания так ведет себя с клиентами. Но это хотя бы не по скотски обрезать доступ и отмораживаться как свиньи из Яндекса.

А теперь, как это же выглядит в РФ. Давайте попробуем из ДНР подключиться к РСЯ? Получится?

Нет не получится. Раньше они всем давали отписки, дескать «не резидент» и досвидос. Это укладывалось в законодательство РФ. А что теперь? А теперь просто вы не сможете заполнить своих платежных данных с реквизитами, потому что надо указать регистрацию, а этих регионов РФ нет в списке. И внутри этого сельского туалета(компании Яндекс) установлены внутренние директивы для сотрудников поддержки. И по этим директивам они не посылают вас напрямую на*уй (но идти вам именно туда), со своей регистрацией в Донецке или Луганске. Чтобы вы не побежали с этим на*уй в суд. А остальное очень трудно доказуемо.

Вы можете спросить у болванчиков из поддержки, а почему нет регионов в списке? Вам ответят, сейчас временные ограничения. А что за ограничения, почему, покажите? Вам ответят, вашего адреса в ФИАС нет. Вы скажете, да вот же ФИАС, да вот же мой адрес там уже второй год как добавлен. Они тогда скажут, мы переходим на другие базы, мы работаем над этим. Вы спросите, а долго ещё? Разговор на этом замкнется в круг — временно. И т.д и т.п. отписки по внутренним директивам. Знаете что временно для них? Я покажу что временно на самом деле.

Давайте посмотрим в Яндекс карты. Вы думаете сепаратисты из Яндекса собираются переходить на другие базы когда то? Нет, они просто на фронтенде скрыли страну, чтобы всякие там патриоты сильно не бухтели, а api как и раньше показывает — «Украина». Только взгляните какая «прелесть». Они ждут…

Российская ли это компания вообще? А как новостной агрегатор Яндекса разжигал будущую войну с 2014 года… Ладно это всё лирика и политота. Просто в разрезе пример, как оно всё работает в РФ и на Западе и почему… Потому что отношение такое, в первую очередь к себе и клиентам!

UPD: и немного про сервисы VK…

Это каким наглухо пи…данутым разработчиком надо быть чтобы придумать такое? После регистрации, которую подтверждаешь по смс, надо посмотреть 2 суко несчастных ключа, на одной странице в 20 пикселях друг от друга, и для каждого отправить ещё 2 смс, которые идут суко пол года. Бл…ть чтоб вас сука разорвало на…уй!

Оставить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *