Можно просто взять XML интерфейс одного из банков, средствами PHP распарсить нужную валюту, сохранить данные в кэш, чтобы больше не тревожить банк.
Кэш можно обновлять с заданным интервалом, получая в нужный момент актуальные данные для конвертера.
Всё это можно сделать с применением AJAX, адаптивной вёрстки и прочих плюшек, в итоге получив красивый и функциональный виджет для сайта или даже целый модуль для вашей CMS.
Однако что можно сделать, если нет возможности применить серверную обработку данных?
Если никак нельзя получить данные с помощью PHP?
Если просто нет доступа к скриптам на сервере (такое часто встречается, если используется конструктор сайтов или лендингов)?
Как бы поступили Вы?
И вот представьте, что именно такие исходные данные заказчик добавляет в техническое задание сайта, когда работа уже подходит к концу.
Всё уже разработано: загрузка данных по валютам из банка, парсинг валют, кэширование результатов, вывод их пользователю, виджет и всё всё всё…
Но не будем унывать раньше времени: непростые задачи помогают повысить квалификацию.
Итак, что мы имеем:
Мы будем использовать сторонний сервис для получения данных с сайта банка: https://query.yahooapis.com
Который любезно получит для нас данные с помощью того же jQuery get:
$.get('https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%3D%27httpss%3A%2F%2Fwww.cbr.ru%2Fscripts%2FXML_daily.asp%3Fdate_req%3D' + curDate + '%27&format=json&callback=', function(data) { if (data != 'ERR') { var rates = ''; $(data.query.results.ValCurs.Valute).each(function(key, value) { if (-1 != $.inArray(value.CharCode, curCodes)) { curRate = value.Value.substring(0,5); curRate = curRate.replace(/,/g, "."); curRate = parseFloat(curRate); curRate = curRate.toString().substring(0,5); } $('#rates').html(rates); $('#rate-cur').html(curRate); $('#rate-rur').val(curRate); }); } else { $('#rates').html('<li>Данные недоступны</li>'); $('#rate-cur').html('ERR'); }
Ну а дальше мы просто подставляем нужные данные в наш конвертер и имеем всегда свежий курс валют без использования серверных скриптов.
И вот, что в итоге у нас получилось:
И всё хорошо до того момента, пока Ваш сайт не начинает содержать материалы, которые нежелательны для просмотра лицам не достигшим совершеннолетия.
Тут то и приходят разнообразные личности с проверкой и контролем. И ваш сайт очень быстро оказывается в списках запрещённых.
И вот вы уже теряете посетителей.
А всего-то нужно было установить на сайт предупреждение, обязывающее пользователя ответить на вопрос: исполнилось ли ему 18 лет.
Для различных CMS этот вопрос решается различными путями:
Но что Вы будете делать, если Ваш сайт построен на обычном HTML, без применения динамического контента?
Если Вы не можете применить PHP с проверкой cookies?
Возможно ли реализовать данное решение на голом JavaScript+HTML?
Конечно возможно!
Именно так мы и поступили, когда появился заказ на разработку такого плагина к интернет-магазину на Webasyst.
Дело в том, что Webasyst сейчас представляет облачную платформу, которая вроде бы и удобна для пользователя, но не даёт использовать все преимущества PHP.
Поэтому мы использовали только jQuery и плагины к нему, а также bootstrap 3 для внешнего оформления всплывающего окна с предупреждением.
Причём подгрузка bootstrap происходит динамично с помощью java script в зависимости от действий пользователя.
При первом визите пользователя ему показывается всплывающее окно с вопросом о совершеннолетии, которое закрывает весь контент.
Если пользователь отвечает утвердительно на вопрос о возрасте, то ему устанавливается cookie и окно скрывается.
При следующем визите на сайт проверяется наличие cookie и, если всё в порядке, то окно не показывается.
Если же пользователь ответил отказом, то его перенаправляет с сайта на сторонний ресурс.
Вот так выглядит само окно:
А вот реализации его работы:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> <script> (function (factory) { if (typeof define === 'function' && define.amd) { // AMD (Register as an anonymous module) define(['jquery'], factory); } else if (typeof exports === 'object') { // Node/CommonJS module.exports = factory(require('jquery')); } else { // Browser globals factory(jQuery); } }(function ($) { var pluses = /+/g; function encode(s) { return config.raw ? s : encodeURIComponent(s); } function decode(s) { return config.raw ? s : decodeURIComponent(s); } function stringifyCookieValue(value) { return encode(config.json ? JSON.stringify(value) : String(value)); } function parseCookieValue(s) { if (s.indexOf('"') === 0) { // This is a quoted cookie as according to RFC2068, unescape... s = s.slice(1, -1).replace(/"/g, '"').replace(//g, ''); } try { // Replace server-side written pluses with spaces. // If we can't decode the cookie, ignore it, it's unusable. // If we can't parse the cookie, ignore it, it's unusable. s = decodeURIComponent(s.replace(pluses, ' ')); return config.json ? JSON.parse(s) : s; } catch(e) {} } function read(s, converter) { var value = config.raw ? s : parseCookieValue(s); return $.isFunction(converter) ? converter(value) : value; } var config = $.cookie = function (key, value, options) { // Write if (arguments.length > 1 && !$.isFunction(value)) { options = $.extend({}, config.defaults, options); if (typeof options.expires === 'number') { var days = options.expires, t = options.expires = new Date(); t.setMilliseconds(t.getMilliseconds() + days * 864e+5); } return (document.cookie = [ encode(key), '=', stringifyCookieValue(value), options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE options.path ? '; path=' + options.path : '', options.domain ? '; domain=' + options.domain : '', options.secure ? '; secure' : '' ].join('')); } // Read var result = key ? undefined : {}, // To prevent the for loop in the first place assign an empty array // in case there are no cookies at all. Also prevents odd result when // calling $.cookie(). cookies = document.cookie ? document.cookie.split('; ') : [], i = 0, l = cookies.length; for (; i < l; i++) { var parts = cookies[i].split('='), name = decode(parts.shift()), cookie = parts.join('='); if (key === name) { // If second argument (value) is a function it's a converter... result = read(cookie, value); break; } // Prevent storing a cookie that we couldn't decode. if (!key && (cookie = read(cookie)) !== undefined) { result[name] = cookie; } } return result; }; config.defaults = {}; $.removeCookie = function (key, options) { // Must not alter options, thus extending a fresh object... $.cookie(key, '', $.extend({}, options, { expires: -1 })); return !$.cookie(key); }; })); //Загружаем bootstrap 3, если cookie нет if(!$.cookie('warning_dialog_cookie')){ document.write('<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">'); document.write('<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>'); } $(document).ready(function(){ if(!$.cookie('warning_dialog_cookie')){ $('#myModal').modal('show'); } $('#warning_button_yes').click(function(){ $.cookie('warning_dialog_cookie', 'yes', { expires: 1 }); $('#myModal').modal('hide'); }); $('#warning_button_no').click(function(){ $.removeCookie('warning_dialog_cookie'); document.location.href = '/'; //здесь адрес, куда редиректить в случае отказа }); }); </script> </pre> <pre><!-- Здесь можно прописать стили модального окна --> <style> .modal-backdrop.in { opacity: 1; background: #965623; } </style> <!-- Modal --> <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" style="display: none;"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header text-center"> <h4 class="modal-title" id="myModalLabel">Вам уже исполнилось 18 лет?</h4> </div> <div class="modal-body text-center"> Содержание сайта предназначено для просмотра исключительно лицам достигшим совершеннолетия! </div> <div class="modal-footer"> <div class="row"> <div class="col-xs-6 text-center"> <button type="button" class="btn btn-block btn-success" id="warning_button_yes">Да</button> </div> <div class="col-xs-6 text-center"> <button type="button" class="btn btn-block btn-danger" id="warning_button_no">Нет</button> </div> </div> </div> </div> </div> </div>]]>
Особенности:
]]>
Шлюз работает под управлением плагина для WordPress wp-recall
и является дополнением к нему.
Также можем предложить разработку других платежных шлюзов для этого плагина (wp-recall) и других систем.
Обращайтесь, будем рады помочь!
]]>
В Битрикс24 есть отличный инструментарий бизнес-процессов. С помощью него можно сделать практически всё, что угодно. Что ещё лучше — есть даже поддержка произвольного PHP кода.
И вот, когда Вы уже обрадовались, что попали в рай для программиста, наступает небольшое огорчение — облачная версия Битрикс24 не поддерживает произвольный PHP код в бизнес-процессах.
Вот что по этому поводу говорит поддержка: https://forums.bitrix24.ru/forum15/topic4501/
И казалось бы всё! Выхода нет! Жизнь окончена! Занавес! Но программисты не сдаются просто так! Только не сейчас, когда счастье было таким возможным!
Если гора не идёт к Магомету… Правильно: если код не может быть выполнен на этом сервере (в облаке), он может быть выполнен на другом сервере.
Но тут тоже есть ряд проблем:
Расскажу всё по порядку. Недавно к нам обратилась одна компания именно с такой задачей: выполнить произвольный код PHP в облачной версии Битрикс24.
Код должен был получать параметры от бизнес-процесса, который обрабатывает лид, и отправлять некоторые данные для статистики в Google Analytics.
И вот как мы это сделали.
В бизнес процессах Битрикс24 есть чудесная возможность отправки оповещений по E-mail. И мы решили отправлять данные для скрипта по почте.
На другом конце этой цепочки установили cron скрипт, который каждые несколько минут проверяет почту (на которую мы шлём параметры для скрипта) и, если находит непрочитанные письма определённого формата, читает из них параметры и выполняет.
Чтобы не заморачиваться с SSL сертификатами, мы использовали почтовик ukr.net
И вот, что у нас получилось:
<?php //Задаём время исполнения скрипта побольше set_time_limit(4000); // Connect to mail $imapPath = '{imap.ukr.net:143}INBOX'; $username = '[email protected]'; $password = 'your_pass'; // try to connect $inbox = imap_open($imapPath,$username,$password) or die('Cannot connect to email: ' . imap_last_error()); // search and get unseen emails, function will return email ids $emails = imap_search($inbox,'UNSEEN'); $output = ''; if(count($emails) > 0) { foreach($emails as $mail) { $headerInfo = imap_headerinfo($inbox,$mail); $output .= '<strong>Subject:</strong> ' . iconv_mime_decode($headerInfo->subject).'<br/>'; $output .= '<strong>To:</strong> ' . $headerInfo->toaddress.'<br/>'; $output .= '<strong>Date:</strong> ' . $headerInfo->date.'<br/>'; $output .= '<strong>From:</strong> ' . $headerInfo->fromaddress.'<br/>'; imap_setflag_full($inbox,$mail,"Seen"); //помечаем просмотренным $emailStructure = imap_fetchstructure($inbox,$mail); $subject = iconv_mime_decode($headerInfo->subject); if(!isset($emailStructure->parts)) { $output .= '<strong>Body:</strong> ' . imap_body($inbox, $mail, FT_PEEK) . '<br/>'; $post_data = imap_body($inbox, $mail, FT_PEEK); } else { // } echo $output; //Проверяем тему if($subject == 'Post data for send GA') { //Проверяем установлен ли CURL и заданы ли нужные нам параметры в письме if( $curl = curl_init() AND !empty($post_data)) { $post_url = 'https://www.google-analytics.com/collect'; echo '<strong>POST url:</strong> ' . $post_url . '<br/>'; echo '<strong>POST data:</strong> ' . 'payload_data&' . $post_data . '<br/>'; //Отправляем данные на сервер GA curl_setopt($curl, CURLOPT_URL, $post_url); curl_setopt($curl, CURLOPT_RETURNTRANSFER,true); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, 'payload_data&' . $post_data); //Читаем ответ сервера GA $out = curl_exec($curl); echo '<strong>GA server answer:</strong><br><br>'; echo '<strong>REQUEST HEADERS:</strong><br>'; $headers = curl_getinfo($curl); echo '<strong><i>url:</i> ' . $headers['url'] . '<br/>'; echo '<i>httpss_code:</i> ' . $headers['httpss_code'] . '<br/></strong>'; echo '<i>content_type:</i> ' . $headers['content_type'] . '<br/>'; echo '<i>header_size:</i> ' . $headers['header_size'] . '<br/>'; echo '<i>request_size:</i> ' . $headers['request_size'] . '<br/>'; echo '<i>filetime:</i> ' . $headers['filetime'] . '<br/>'; echo '<i>ssl_verify_result:</i> ' . $headers['ssl_verify_result'] . '<br/>'; echo '<i>redirect_count:</i> ' . $headers['redirect_count'] . '<br/>'; echo '<i>total_time:</i> ' . $headers['total_time'] . '<br/>'; echo '<i>namelookup_time:</i> ' . $headers['namelookup_time'] . '<br/>'; echo '<i>connect_time:</i> ' . $headers['connect_time'] . '<br/>'; echo '<i>pretransfer_time:</i> ' . $headers['pretransfer_time'] . '<br/>'; echo '<i>size_upload:</i> ' . $headers['size_upload'] . '<br/>'; echo '<i>size_download:</i> ' . $headers['size_download'] . '<br/>'; echo '<i>speed_download:</i> ' . $headers['speed_download'] . '<br/>'; echo '<i>speed_upload:</i> ' . $headers['speed_upload'] . '<br/>'; echo '<i>download_content_length:</i> ' . $headers['download_content_length'] . '<br/>'; echo '<i>upload_content_length:</i> ' . $headers['upload_content_length'] . '<br/>'; echo '<i>starttransfer_time:</i> ' . $headers['starttransfer_time'] . '<br/>'; echo '<i>redirect_time:</i> ' . $headers['redirect_time'] . '<br/>'; echo 'RESPONSE:<br>'; echo $out; curl_close($curl); } else { //Не установлен CURL или не заданы параметры echo "ERROR: no curl OR no post data!<br>"; } } else { //Не та тема письма echo "ERROR: no valid email subject!<br>"; } echo '<hr>'; $output = ''; } } else { //Нет новых писем echo 'ERROR: no mails!'; } // colse the connection imap_expunge($inbox); imap_close($inbox); ?>]]>
Конвертер валют от портала придаст вашему сайту больше функциональности и повысит его информативность.
Основные возможности конвертера:
Все расчеты производятся «на лету»
Округление добавляет реалистичности расчетам
Ввведя сумму в поле «ПОЛУЧАЮ» валютного калькулятора — вы получите расчет обратной конвертации
Возможен учет комиссии конвертации
Установка
Стандартная установка через marketplace (Панель администрирования / Marketplace / Каталог решений). Компонент не требует дополнительных действий по установке.
]]>
Установка
Стандартная установка через marketplace (Панель администрирования / Marketplace / Каталог решений). Компонент не требует дополнительных действий по установке.
Сайт интернет-магазина по продаже электроинструмента и запасных частей к нему.
Система управления контентом (CMS): WordPress
Задачи:
Срок реализации: 2 дня
]]>Сайт интернет-магазина по продаже электроинструмента и запасных частей к нему.
Адрес сайта: https://toolpark.ru/
Система управления контентом (CMS): 1С Битрикс (редакция «Малый бизнес»)
Задачи:
Срок реализации: 30 дней
]]>