Задача
Устроить автоматический прием денег на свой яндекс кошелек.
Вводные:
- Платеж должен быть привязан к 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>