Форма оплаты на кошелек Яндекс деньги для сайта без SSL на php

Задача

Устроить автоматический прием денег на свой яндекс кошелек.

Вводные:

  • Платеж должен быть привязан к email пользователя,
  • Сайт работает на PHP 5.3
  • Операция должна начислять дни в соответствии с выбранным периодом (1-3 месяцев)
  • Следует использовать существующую базу данных на WordPress сайте.

К сожалению рабочий сайт нам не может быть полезен во время тестирования так как наш хостер предусмотрительно отключил логирование «наружу», поэтому я развернул полную копию своего сайта локально с помощью приложения OpenServer, по адресу localhost.

Документация

Для сайта на http (в отличие от https) извещение о платеже приходит в сокращённом виде

https://money.yandex.ru/doc.xml?id=526991&from=isrch :

operation_id = 441361714955017004
notification_type = card-incoming
datetime = 2013-12-26T08:28:34Z
sha1_hash = ac13833bd6ba9eff1fa9e4bed76f3d6ebb57f6c0
sender =
codepro = false
currency = 643
amount = 98.00
withdraw_amount = 100.00
label = ML23045

Существует тестовая кнопка от Яндекса, которая будет посылать запрос на указанную нами php страницу https://money.yandex.ru/myservices/online.xml , здесь нам нужен СЕКРЕТ и нужно указать адрес на нашу страницу. К сожалению кнопка «Протестировать» в целом бесполезна.

Реализация. Форма для создания POST данные

Для тестирования нужно создать html форму в соответствии с рекомендациями назвал index1.html, она содержит ровно тот набор данных что нам необходим.

Код index1.html:

Посмотреть код

<form action="payment.php" method="post" >

<br>operation_id:<input type="text" name="operation_id" value="test-notification" >
<br>notification_type:<input type="text" name="notification_type" value="p2p-incoming" >
<br>datetime:<input type="text" name="datetime" value="2017-01-06T19:43:37Z" >
<br>sender:<input type="sender" name="sender" value="41001000040" >
<br>sha1_hash:<input type="text" name="sha1_hash" value="2e0f6de10d9f621b80e97cf64a424e54376c883" >
<br>codepro:<input type="text" name="codepro" value="false" >
<br>currency:<input type="text" name="currency" value="643" >
<br>amount :<input type="text" name="amount" value="49" >
<br>withdraw_amount:<input type="text" name="withdraw_amount" value="50" >
<br>label:<input type="text" name="label" value="1@gmail.com:1_month" style="width: 300;">
<button type="submit">Отправить</button>

</form>

Отдельно отмечу label он содержит два значимых значения – это email пользователя и условный флаг-значение периода оплаты в моем случае 1 месяц, с разделителем – двоеточие.

Далее код файла php для приема оповещений о платеже. Необходимо добавить поле vip типа DateTime в таблицу users

Код payment.php

Посмотреть код

//Подключаем функции работы с БД WordPress

require_once( dirname(__FILE__) . '/wp-load.php' );

$yandex_secret = '*******';//Секретный код яндекса
global $wpdb;//поле  для работы с БД  
$label = esc_sql(trim($_POST['label']));            // Метка платежа. <E-mail>:<TARGETS>
$parts = explode(':', $label, 2); //Разбиваем label
$notification_type = $_POST['notification_type']; // p2p-incoming / card-incoming - с кошелька / с карты
$operation_id = $_POST['operation_id'];      // Идентификатор операции в истории счета получателя.
$amount = $_POST['amount'];            // Сумма, которая зачислена на счет получателя.
$withdraw_amount = $_POST['withdraw_amount'];   // Сумма, которая списана со счета отправителя.
$currency = $_POST['currency'];            // Код валюты — всегда 643 (рубль РФ согласно ISO 4217).
$datetime = $_POST['datetime'];          // Дата и время совершения перевода.
$sender = $_POST['sender'];            // Для переводов из кошелька — номер счета отправителя. Для переводов с произвольной карты — параметр содержит пустую строку.
$codepro = $_POST['codepro']; // Для переводов из кошелька — перевод защищен кодом протекции. Для переводов с произвольной карты — всегда false.
$user_email = $parts [0];
$targets = $parts[1]; //
$sha1_hash = $_POST['sha1_hash']; // SHA-1 hash параметров уведомления.

//Платеж с кодом протекции, автоматически обработать не можем
    if ($r['codepro'] === true) {
exit ($user_email, $email_subject, 'Ошибка! Платеж с кодом протекции, автоматически обработать не можем');
}

// проверка хеш
$data_hash = $notification_type.'&'.$operation_id.'&'.$amount.'&'.$currency.'&'.$datetime.'&'.$sender.'&'.$codepro.'&'.$yandex_secret.'&'.$label;

if (hash("sha1", $data_hash) != $sha1_hash)  {
exit("SHA верификация не произошла = " . $message);
}//Проверям соответсвие суммы периодуif($targets == "1_month" && $withdraw_amount == '50.00' ||  $targets == "3_month" && $withdraw_amount == '130.00'){}
else{
exit('Ошибка! Неверная сумма для указанного периода : '.$withdraw_amount.' '.$label);
}//Получаем поле из БД$vip = $wpdb->get_var("SELECT vip FROM $wpdb->users WHERE user_email = '".$user_email."'");

$days = "31 day";
if($targets == "1_month"){
$days = "31 day";
}
else if($targets == "3_month"){
$days = "93 day";    }

$date_time_now = new DateTime();

if(!empty($vip))
{
$vip = date_create_from_format('Y-m-d H:i:s', $vip);//так как это строка
if($vip < $date_time_now) {
$vip = $date_time_now;        }
}
else  {        $vip = $date_time_now;
}
$vip->modify("+".$days);

$r = $wpdb->query("UPDATE $wpdb->users SET last_operation_id = '" . $operation_id . "', vip = '" . $vip->format('Y-m-d H:i:s') . "'  WHERE user_email = '$user_email' LIMIT 1");
if (!$r) {
exit("Ошибка в обновление данных о клиенте!");
}exit('OK');

Код упрощен, значение хэш для теста необходимо определить самостоятельно.Форма для создания кастомных данных для сервиса Яндекс деньги
 

Посмотреть код

<form class="form" method='POST' action="https://money.yandex.ru/quickpay/confirm.xml">
<input type='hidden' name='receiver' value='410000000000000'>
<input type='hidden' name='formcomment' value='Оплата VIP'>
<input type='hidden' name='short-dest' value='Оплата VIP'>
<input type='hidden' name='quickpay-form' value='donate'>
<input type='hidden' name='comment' value='Оплата VIP статуса>
<input type='hidden' name='need-fio' value='false'>
<input type='hidden' name='need-email' value='false'>
<input type='hidden' name='need-phone' value='false'>
<input type='hidden' name='need-address' value='false'>
<input id='label' type='hidden' name='label' value=''>                    <input class='input__control' id='email' value='' maxlength='256'><div>
<div>
<label class='label-text'>VIP статус на</label>
</div>
<label class='form-label'>
<input id='radio_1_month' name='targets' value='1_month' type='radio' checked>
<span class='label-text'>1 месяц</span>
</label><br>
<label class='form-label'>
<input id='radio_3_month' name='targets' value='3_month' type='radio'>
<span class='label-text'>3 месяца</span>
</label><br>
</div><input name='sum' aria- value='50.00' readonly><div >
<label >
<input name='paymentType' value='PC' type='radio' checked>
<span class='label-text'></span>
<span>
<i aria-hidden='true'></i>
</span>
</label><br>
<label >
<input name='paymentType' value='AC' type='radio'>
<span class='label-text'></span>
<span>
<i aria-hidden='true'></i>
</span>
</label><br>
<label >
<input name='paymentType' value='MC' type='radio'>
<span class='label-text'></span>
<span>
<i aria-hidden='true'></i>
</span>
</label>
</div><button type='submit' autocomplete='off' tabindex='0'>
<span class='button2__text'>Оплатить</span>
</button></form> /Установить сумму при перемене радио батона периода
function set_sum_event()
{
var targets = document.getElementsByName('targets');

for(i = 0;i < targets.length; i++)
{
if(targets[i].checked) {
var targets_val = targets[i].value;
console.log(targets_val);
var sum_element = document.getElementsByName('sum')[0];
if (targets_val === '1_month') {
sum_element.value = '50.00';
}
else if (targets_val === '3_month') {
sum_element.value = '130.00';
}
break;
}
}
}

Скрипт для отработки переключающихся радио кнопок:

Посмотреть код

<script>
 //Установить сумму при перемене радио батона периода
            function set_sum_event()
            {
                var targets = document.getElementsByName('targets');

                for(i = 0;i < targets.length; i++)
                {
                    if(targets[i].checked) {
                        var targets_val = targets[i].value;
                        console.log(targets_val);
                        var sum_element = document.getElementsByName('sum')[0];
                        if (targets_val === '1_month') {
                            sum_element.value = '50.00';
                        }
                        else if (targets_val === '3_month') {
                            sum_element.value = '130.00';
                        }
                        break;
                    }
                }
            }
window.onload = function() {

var radio_1_month = document.getElementById('radio_1_month');
radio_1_month.addEventListener('change', set_sum_event);

var radio_3_month = document.getElementById('radio_3_month');
radio_3_month.addEventListener('change', set_sum_event);

var radio_6_month = document.getElementById('radio_6_month');
radio_6_month.addEventListener('change', set_sum_event);

var form = document.getElementsByClassName('form')[0];

form.addEventListener('submit', function(e) {
if (/\S+@\S+\.\S+/.test(document.getElementById('uniq1').value)){

//Заносим 2 поля в label
var label = document.getElementsByName('label')[0];
var email = document.getElementById('uniq1');
var email = email.value;

var targets_val = '';
var targets = document.getElementsByName('targets');
for(i = 0;i < targets.length; i++)
{
if(targets[i].checked) {
targets_val = targets[i].value;
break;
}
}
label.value = email + ':' + targets_val;
return true;
}

//Показываем popup так как email не указан
e.preventDefault();
var popup = document.getElementsByClassName('popup')[0];

popup.setAttribute('class', 'popup_to_top popup_theme_error');
});
}</script>