Обновление стоимости и корзины
После создания платежной сессии иногда возникает необходимость обновить корзину.
Обычно обновление корзины — это асинхронное действие, которое по шагам выглядит так:
- Пользователь меняет состав корзины (или конечную сумму заказа).
- Продавец обновляет данные у себя на сервере.
- Продавец обновляет данные в платежной сессии Yandex Pay.
Проблема в том, что пользователь может начать процесс оплаты где-то между 1 и 2 пунктом, не дождавшись обновленных данных. Таким образом, он нажмет на кнопку и откроет форму Yandex Pay со старой корзиной.
Чтобы избежать подобной ситуации, нужно обновлять корзину с блокировкой кнопки Yandex Pay на время обновления.
Метод paymentSession.update
принимает в качестве аргумента функцию (которая тут же выполняется), результатом работы которой ожидается Promise
. Кнопка блокируется до резолва Promise
.
Пример
function onYaPayLoad() {
const YaPay = window.YaPay;
let activeSession = null;
// Данные платежа
const paymentData = {
env: YaPay.PaymentEnv.Sandbox,
version: 3,
currencyCode: YaPay.CurrencyCode.Rub,
merchantId: '<YOUR_MERCHANT_ID>',
cart: getNewCart(),
};
// Обработчик на получение платежного токена
function onPaymentSuccess(event) {
console.log(`OrderId — ${event.orderId}`);
}
// Обработчик на ошибки при оплате
function onPaymentError(event) {
console.log(`Payment error — ${event.reason}`);
}
// Обработчик на отмену оплаты
function onPaymentAbort(event) {}
// Создать платежную сессию.
YaPay.createSession(paymentData, {
onSuccess: onPaymentSuccess,
onAbort: onPaymentAbort,
onError: onPaymentError,
})
.then(function (paymentSession) {
activeSession = paymentSession;
paymentSession.mountButton(document.querySelector('#button_container'), {
type: YaPay.ButtonType.Checkout,
theme: YaPay.ButtonTheme.Black,
width: YaPay.ButtonWidth.Auto,
});
})
.catch(function (err) {
// Не получилось создать платежную сессию.
});
// Эмуляция обновления корзины
// apiRequestPromise — Promise api-запроса на обновление корзины на сервисе
onOrderUpdate(function (apiRequestPromise) {
if (!activeSession) {
return console.log('Payment session is not created');
}
const newCart = getNewCart();
// Обновляем корзину с блокировкой кнопки
activeSession.update(async function () {
await apiRequestPromise;
return {
cart: newCart,
};
});
});
}
/**
* Сопроводительные функции для иллюстрации работы
*/
function getNewCart() {
const randomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
const price = 7990;
const count = randomInt(1, 20);
const total = (count * price).toFixed(2);
document.querySelector('#order_amount').innerHTML = Intl.NumberFormat('ru-RU', {
style: 'currency',
currency: 'RUB',
}).format(total);
return {
items: [{ productId: '3', total, quantity: { count } }],
};
}
function onOrderUpdate(cb) {
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const updateButton = document.querySelector('#update_order_button');
updateButton.addEventListener('click', function () {
// Эмуляция Promise'a запроса на обновление корзины на сервере
const apiRequestPromise = wait(2000);
cb(apiRequestPromise);
});
}