Прием платежей на сайте через CloudPayments

Прием платежей через CloudPayments

CloudPayments позволяет принимать платежи через банковские карты, Google Pay, Apple Pay. Данные для платежа вводятся внутри всплывающей формы.



Подключение сервиса

Для подключения сервиса нам понадобится зарегистрироваться, добавить свой сайт в личном кабинете и получить для него Public ID и пароль API. Первый понадобится для проведения платежей, второй - для их подтверждения.

Пароль API добавим в настройки нашего сайта под кодом cloudPaymentsApiCode, его будем использовать в одной из хранимых процедур.

Общая схема работы

При нажатии кнопки “оплатить” на сайте будет происходить следующая последовательность действий:

  1. Отправляем ajax запрос на создание платежа в нашей системе. Получаем id платежа.
  2. Запускаем платеж CloudPayments, куда передаем id платежа.
  3. Если платеж прошел успешно, CloudPayments отправляет уведомление на наш API.
  4. Используя полученный от CloudPayments пароль API в качестве ключа, проверяем подлинность уведомления, и если всё хорошо, подтверждаем платеж.

Далее рассмотрим реализацию каждого из шагов. Для примера будем пополнять баланс пользователя на сайте.

Добавление функционала платежа на страницу

Управление платежом будет происходить с помощью javascript.

В html нужно подключить скрипт cloudPayments, также приведем нашу кнопку оплаты и поле для ввода суммы:

<input type="text" class="balance-input-sum form-control" placeholder="Сумма пополнения">
<button class="btn btn-primary addBalance">Оплатить</button>

<script src="https://widget.cloudpayments.ru/bundles/cloudpayments"></script>

Пример javascript ниже. При нажатии на кнопку “оплатить” делаем запрос на создание платежа (initPayment). После получения id платежа передаем его в функцию pay, которая вызовет диалог ввода платежных данных.

as.cloudPayments = {
  init: function(){
    $(document).on("click", ".addBalance", function(){
      as.cloudPayments.initPayment();
    });
  },
  //функция создания платежа
  initPayment: function(){
    //делаем запрос на создание платежа
    as.sys.request("finances", "initPayment", {
      data: { sum: Number($('.balance-input-sum').val() || "0") },
      onSuccess: function(data) {
        var paymentID = data.data[0].paymentID;
        //когда получили id платежа, начинаем оплату
        as.cloudPayments.pay(paymentID);
      }
    });
  },
  //функция платежа
  pay: function(paymentID){
    var widget = new cp.CloudPayments();
    //вызываем диалог платежа
    widget.charge({ // options
            publicId: 'pk_1111111111111111111111',  //public id из личного кабинета
            description: 'Пример оплаты (деньги сниматься не будут)', //назначение
            amount: Number($('.balance-input-sum').val() || "0"), //сумма
            currency: 'RUB', //валюта
            invoiceId: paymentID, //id платежа
            accountId: $('.as-username').val(), //username плательщика
            skin: "mini", //дизайн виджета
            data: {
                //username: 'myProp value' //произвольный набор параметров
            }
        },
        function (options) { // success
            //действие при успешной оплате
            //обновляем страницу
            location.reload();
        },
        function (reason, options) { // fail
            //действие при неуспешной оплате
        });
  }
}

$(function(){
  as.cloudPayments.init();
});

После проведения платежа cloudPayments должен отправить на наш api уведомление о совершении платежа. Создание api рассмотрим ниже.

Прием ajax запросов на создание платежа

Для создания платежей делается запрос finances_initPayment.

Ниже приведен пример процедуры для запроса. Создаем для нашего пользователя новый платеж в таблице fin_finances со статусом “Предварительный”. Единственный параметр для запроса - sum (сумма платежа).

Возвращаем ID платежа.

CREATE PROCEDURE [dbo].[request_finances_initPayment]
    @parameters DictionaryParameter READONLY,
    @username nvarchar(32)
AS
BEGIN
    select '' Msg, 1 Result

    declare @counteragentID int = (select id from ctr_contragents where username=@username)
    declare @accountID int = (select id from fin_accounts where contragentID=@counteragentID)

    declare @statusID int
    select @statusID = id from fin_financeStatuses where name = N'Предварительный'

    declare @sum decimal = (select Value from @parameters where [Key]='sum')

    insert into fin_finances (accountToID, sum, typeID, statusID,  created)
    values (@accountID, @sum, 1, @statusID, getdate())

    declare @paymentID int = scope_identity()

    select @paymentID paymentID
END

API для приема уведомлений о платежах

Добавляем метод входящего API.

Код сущности в нашем случае - finances, код - confirmPayment.

“Без Token?” - да.

Адрес полученного API нужно указать в настройках сайта в личном кабинете CloudPayments в разделе “Pay уведомление”.

Полный список параметров, которые входят в уведомление и будут доступны в хранимой процедуре, есть в документации сервиса https://developers.cloudpayments.ru/#pay.

Внутри хранимой процедуры нам нужно будет подтвердить подлинность уведомления и подтвердить наш платеж. Подробности смотрите в комментариях внутри примера.

Текст хранимой процедуры для API: 

CREATE PROCEDURE [dbo].[api_finances_confirmPayment]
@parameters ExtendedDictionaryParameter READONLY,
@username nvarchar(256)
as
begin
    --часть 1 - подтверждение подлинности уведомления
    --нужно рассчитать хеш уведомления, используя пароль API в качестве ключа, и сравнить его с тем, что пришел в параметре Content-HMAC

    --полный текст уведомления (тело запроса)
    declare @notificationBody nvarchar(max) = (select Value2 from @parameters where [Key]='InputStream')
    --пароль API (достаем из настроек)
    declare @notificationKey nvarchar(max) = (select value from as_settings where code='cloudPaymentsApiCode')

    --рассчитываем хеш
    declare @notificationHash varbinary(64) = dbo.as_HMAC('SHA2_256', dbo.as_NCharToUTF8Binary(@notificationKey, 1), dbo.as_NCharToUTF8Binary(@notificationBody, 1))

    --кодируем хеш в виде base64
    declare @notificationHashBase64 nvarchar(128) = dbo.as_binaryToBase64(@notificationHash)

    --эталонный хеш, с которым будем сравнивать тот, что получился у нас
    declare @notificationHmac nvarchar(128) = (select Value2 from @parameters where [Key]='Content-HMAC')

    --если они совпадают, эта переменная будет равна 1. В этом случае подтверждаем платеж.
    declare @notificationIsCorrect bit = case when @notificationHmac=@notificationHashBase64 then 1 else 0 end
    declare @paymentStatus nvarchar(64) = (select Value2 from @parameters where [Key]='Status')
    if (@notificationIsCorrect = 1 and @paymentStatus='Completed') begin
        --часть 2 - подтверждение платежа
        declare @paymentID int = (select Value2 from @parameters where [Key]='InvoiceID')
        declare @paymentUsername nvarchar(256) = (select Value2 from @parameters where [Key]='AccountID')
        declare @sum decimal = (select Value2 from @parameters where [Key]='Amount')
        declare @counteragentID int = (select id from ctr_contragents where username=@paymentUsername)
        declare @accountID int = (select id from fin_accounts where contragentID=@counteragentID)

        declare @statusDoneID int
        select @statusDoneID = id from fin_financeStatuses where name = 'Проведен'

        --обновляем статус платежа с "предварительный" на "проведен"
        update fin_finances
        set statusID=@statusDoneID,
            completed=getdate()
        where accountToID=@accountID and id=@paymentID

        --добавляем сумму платежа к балансу пользователя
        update fin_accounts set balance = isnull(balance,0) + @sum where id = @accountID
    end

    -- SELECT 1 - вывод метаданных о результате операции метода API
    select '' Msg, 1 Result, 0 errorCode

    -- SELECT 2 -  вывод самих данных в API (в случае проблем проверьте что этот запрос приходит непустой)
    select 1 where 1=0
end


Тестирование

После добавления платежи можно протестировать.

В документации https://developers.cloudpayments.ru/#testirovanie есть набор тестовых банковских карт, на которых можно проверить работу системы.

Например, на карту номер 4242 4242 4242 4242 платеж должен всегда проходить успешно. Срок карты указывается любой не просроченный.

Переключение в боевой режим Cloud Payments

Происходит в ручном режиме через оператора системы CloudPayment.

При этом производится проверка сайта на предмет соответствия требованиям, описанным здесь -  https://cloudpayments.ru/wiki/podkluchenie/poryadok_podkluchenia/requirements

Основные требования: 

  • контакты рабочие, 
  • договор оферты на сайте, 
  • прозрачная схема оплаты
  • описана  процедура возврата

Также до этого момента должен быть подписан договор с CloudPayments. 

Режим работы Маркетплейс  CloudPayments

Есть агент (площадка) и субагенты (поставщики на площадке).

С агентом подписывается агентский договор. Субагенты работают с CloudPayments по оферте.  

По каждому субагенту в CloudPayments передается информация (видимо в форме некоего документа, анкета) с юридическими данными и банковскими реквизитами субагента. 

При оплате посетителем на площадке передается идентификатор поставщика, на основе которого и осуществляется оплата. 

Оплаты производятся на следующий рабочий день. 

Ссылки

  • Про режим маркетплейс https://cloudpayments.ru/about-system/marketplacehttps://cloudpayments.ru/for-who/for_marketplace
  • Требования к сайту: https://cloudpayments.ru/wiki/podkluchenie/poryadok_podkluchenia/requirements
  • Ссылка на сайт документацией CloudPayments https://developers.cloudpayments.ru/

Проблемы

Приходит пустое тело InputStream в процедуру action

Сделайте имя метода малыми буквами. Также попробуйте убрать из web.config правило редиректа  LowerCaseUrl

Falcon Space - функциональная веб-платформа разработки на узком стеке MS SQL/Bootstrap. Вводная по Falcon Space
Насколько полезной была статья?

Google поиск по нашей документации

Выгода от использования Falcon Space

В 2-3 раза экономнее и быстрее, чем заказная разработка
Более гибкая, чем коробочные решения и облачные сервисы
Используйте готовые решения и изменяйте под свои потребности
Нужна бесплатная консультация?
Планируете делать веб-проект?
Сайт использует Cookie. Правила конфиденциальности OK