[Из песочницы] Создаём сайт, используя Laravel и Recurly. Часть 205.05.2014 17:48
Добрый день, Хабр! После изучения первой части, я начал искать вторую, но её не оказалось, поэтому решил сам написать перевод. Итак, начнем.Введение
В первой части данной серии мы создали голый костяк сайта с подписками на основе Laravel. Так же, мы создали сайт с ролями и создали распределение ролей для зарегистрированных пользователей. Теперь мы подошли к тому моменту, где мы можем создать и выполнить регистрацию, авторизацию и выход.В этой части мы будем интегрировать Recurly для настройки наших платных планов членства.Приступаем к работе
Есть две библиотеки Recurly — клиентская библиотека PHP, которую мы ранее установили с помощью composer (в первой части) и Recurly JS. Recurly JS — это клиентская библиотека для динамической интеграции формы, которая безопасно обрабатывает информацию с карт.Информация карт размещается на серверах Recurly, а не в нашем веб-приложении, что уменьшает нашу головную боль.Скачаем библиотеку Recurly JS и скопируем recurly.min.js из папки сборки в папку public/js/libs и добавим его в макете перед закрывающим тегом:
Мы также должны использовать CSS-стили, которые используются для отображения формы оплаты. Создайте каталог в директории css/recurly и скопируйте в него директорию themes, а затем мы будем ссылаться на него в соответствующем разделе нашего макета
Когда вы первый раз залогинитесь после создания учетной записи с Recurly, вам предложат создать свои планы подписок. В первой части мы создали три разных уровня подписок — бронза, серебро и золото. Вы всегда можете изменить их или добавить новые, но нет никакого вреда в том, что мы сделаем это сейчас.Создайте план под названием Бронзовый; Будьте внимательны, нужно что бы план кода был установлен «bronze» (в нижнем регистре). Установить цену — я написал £ 4,99 в месяц, но вы можете выбрать любую сумму и / или сроки, которые вам нравится. При необходимости вы можете установить одноразовую плату или бесплатный ознакомительный период.
Повторите процесс еще два раза для настройки серебряного (код: «silver») и золотого (код: «gold») планов. Я установил минимум при £ 9.99 и £ 14,99 в месяц соответственно максимум.
Теперь перейдите в админ-панель Recurly, где есть несколько вещей, которые мы должны настроить, а также найти необходимую информацию для настройки вашего приложения. Нажмите доступ API на левой стороне. Щелкните Включить доступ API. Запишите свой ключ API, и ваш поддомен.
Теперь перейдите в Recurly.js на левой стороне (под Разработчик (Developer)). Щелкните Включить Recurly.js и Transparent Post API. Запишите ваш секретный ключ.
Теперь создайте файл конфигурации Recurly в папке app/config/recurly.php, заменяя значения с теми, которые вы только что записали вместе с трехзначным кодом, который отображает выбранную вами валюту по умолчанию (например, USD, GBP, AUD):
'YOUR-API-KEY',
'private_key' => 'YOUR-PRIVATE-KEY',
'subdomain' => 'YOUR-SUBDOMAIN',
'default_currency' => 'XYZ'
);
Теперь перейдем к всплывающим уведомлениям на левой стороне. Нажмите кнопку настроить. Введите URL адрес вашего приложения включая /recurly, например www.example.com/recurly. Оставьте поля HTTP авторизация Имя пользователя (Username) и HTTP авторизация пароля (Password) пустыми на данный момент.Страница регистрации
Теперь, давайте создадим страницу регистрации, которая позволит потенциальным клиентам выбирать для себя план. Создайте по этому пути app/views/home файл signup.blade.php со следующим содержанием:
@extends ('layouts.default')
@section ('content')
@stop
Конечно, если вы хотите обеспечить своевременное обновление цен, то нужно использовать Recurly API и заполнять эти данные в шаблоне автоматически.Теперь добавьте следующие строки в css/style.css:
.pricing-table .plan {
background-color: #f3f3f3;
text-align: center;
}
.plan: hover {
background-color: #fff;
}
.plan {
color: #fff;
background-color: #5e5f59;
padding: 20 px;
}
.plan-name-bronze {
background-color: #665D1E;
color: #fff;
padding: 20 px;
}
.plan-name-silver {
background-color: #C0C0C0;
color: #fff;
padding: 20 px;
}
.plan-name-gold {
background-color: #FFD700;
color: #fff;
padding: 20 px;
}
.pricing-table-bronze {
background-color: #f89406;
color: #fff;
padding: 20 px;
}
.pricing-table .plan .plan-name span {
font-size: 20 px;
}
.pricing-table .plan ul {
list-style: none;
margin: 0;
}
.pricing-table .plan ul li.plan-feature {
border-top: 1 px solid #c5c8c0;
padding: 15 px 10 px;
}
.pricing-three-column {
margin: 0 auto;
width: 80%;
}
.pricing-variable-height .plan {
display: inline-block;
float: none;
margin-left: 2%;
vertical-align: bottom;
zoom:1;
*display: inline;
}
.plan-mouseover .plan-name {
background-color: #4e9a06! important;
}
.btn-plan-select {
font-size: 18 px;
padding: 8 px 25 px;
}
И наконец создадим маршрут в app/routes.php
Route: get ('/signup', function () {
return View: make ('home/signup');
});
Прием платежей
Вот мы и добрались до пункта приема платежей, а именно страница регистрации — оплата.Во первых, давайте изменим user/register POST обратного вызова (callback). Вместо перенаправления на домашнюю страницу, мы будем перемещать пользователя на страницу оплаты. Замените эти строки:
return Redirect: to ('/')→with (
'success',
'Welcome to the site, . Auth: user ()→name. '!'
);
на эти:
Session: put ('register_user', $user);
return Redirect: to ('/user/register/payment');
Нам необходимо расширить макет по умолчанию так, что мы сможем вставлять JavaScript код в футер (низ). Добавьте следующую строку после последнего тега сценария:
@yield ('scripts')
Теперь создадим новый маршрут:
Route: get ('/user/register/payment', function () {
Recurly_js::$privateKey = Config: get ('recurly.private_key');
$plan = 'bronze'; // todo: get this from vars
$user = Session: get ('register_user');
$signature = Recurly_js: sign (array (
'account' => array (
'account_code' => 'user_' . $user→id
),
'subscription' => array (
'plan_code' => $plan,
'currency' => Config: get ('recurly.default_currency')
)
));
return View: make ('user/register')→with (array (
'plan' => $plan,
'subdomain' => Config: get ('recurly.subdomain'),
'currency' => Config: get ('recurly.default_currency'),
'signature' => $signature
));
});
Несколько замечаний по этому коду: Мы должный установить секретный ключ в классе Recurly_js, который мы будем принимать из файла конфигурации созданного ранее.
Данные на подписку (план) мы должны получать из предыдущего этапа, созданного в регистрации. Этот кусок оставлен как самостоятельное упражнение
Нам нужно создать сигнатуру (подпись) для Recurly.js, используя несколько частей информации, в их числе идентификатор пользователя, который мы создаем связывая класс (пользователя) и его ID
Эта подпись передается на ряду с другой информацией в данном представлении
Страница оплаты состоит из двух частей, первая часть — простой HTML:
@extends ('layouts.default')
@section ('content')
@stop
Recurly.js внедряет свой клиентский сгенерированный код формы оплаты в данный div.Далее, мы добавим JavaScript к секции, которая получает вывод внизу шаблона макета:
@section ('scripts')
@stop
Здесь происходит волшебство — Recurly строит форму оплаты и выводит его в div c id #recurly-subscribe, которая требует часть информации, мы пришли к виду, который требует генерируемые подписи.Затем, обратный вызов, который Recurly возвращает после успешной отправки формы, которая определяется в successURL следующими параметрами:
Route: post ('/user/register/confirm', function () {
$recurly_token = Input: get ('recurly_token');
Recurly_js::$privateKey = Config: get ('recurly.private_key');
$result = Recurly_js: fetch ($recurly_token);
var_dump ($result);
});
И снова мы инициализируем Recurly.js с секретным ключем из конфигурации, и используем его для извлечения объекта, представленного токеном, который Recurly посылает в качестве переменной POST (recurly_token). Это будет экземпляром Recurly_Subscription, из которого можно извлечь различную информацию. Я вывожу это с помощью var_dump (), что бы взглянуть на данные.Для начала, давайте получим код плана, что бы узнать на что подписался пользователь:
$plan_code = $result→plan→plan_code;
Теперь, нужно найти соответствующую роль, заметьте — мы дали им имена «bronze», «silver» и «gold».
$role = Role: where ('name', '=', $plan_code)→first ();
Затем получим пользователя из сессии (а затем удалим его из сессии):
$user = Session: get ('register_user');
Session: forget ('register_user');
Далее, мы предоставляем роль для соответствующего нового пользователя:
$user→roles ()→attach ($role);
Затем, мы должны удалить отложенную роль:
$role_pending = $role_pending = Role: where ('name', '=', 'pending')→first ();
DB: table ('role_user')→where ('user_id', '=', $user→id)→where ('role_id', '=', $role_pending→id)→delete ();
Теперь, мы дополнили процесс регистрации приемом платежей, созданием подписок, а так же применять роли для новых учетных записей на основе выбранного пользователем плана.Страница управления учетными записями
Давайте создадим простую страницу, с которой пользователи смогут управлять своим счетом.Очевидно, это будет требовать того, чтобы пользователь вошел в систему, поэтому мы должны применить аутентификационный фильтр.Вместо того, чтобы указывать этот фильтр для каждой защищенной страницы, мы можем поставить все соответствующие маршруты в группу, вот так:
Route: group (array ('before' => 'auth'), function () {
Route: get ('/user/account', function () {
// User must be logged in
});
Route: get ('user/account/billing', function () {
// User must be logged in
});
});
Вызов страницы учетной записи прост:
Route: get ('/user/account', function () {
return View: make ('user/account/index');
});
Теперь адрес вида app/views/user/account/index.blade.php:
@extends ('layouts.default')
@section ('content')
@stop
Начнем с информационного обновления биллинговой страницы. Конечно, мы не храним платежную информацию людей, так как на страницу оплаты, Recurly будет создать и заполнять форму для вас, объявляя (POSTing) новую информацию к Recurly без него когда-нибудь недалеко от вашего веб-приложения.
Route: get ('user/account/billing', function () {
Recurly_js::$privateKey = Config: get ('recurly.private_key');
$account_code = 'user_' . Auth: user ()→id;
$signature = Recurly_js: sign (
array ('account' => array ('account_code' => $account_code))
);
return View: make ('user/account/billing')→with (array (
'subdomain' => Config: get ('recurly.subdomain'),
'currency' => Config: get ('recurly.default_currency'),
'account_code' => $account_code,
'signature' => $signature
));
});
Это очень похоже на страницу оплаты в том плане, что мы инициализируем библиотеки Recurly.js, создавая подписи (хотя и с использованием различной информации) и, проходя через несколько параметров в представление.Путь app/views/user/account/billing.blade.phpследует в значительной степени той же схеме, на страницу оплаты:
@extends ('layouts.default')
@section ('content')
@stop
@section ('scripts')
@stop
Наконец, очень простой обратный вызов, когда пользователь заполнил информацию об оплате:
Route: post ('user/account/billing/confirm', function ()
{
return Redirect: to ('/user/account')→with ('success', 'Your billing information has been updated.');
});
И вот оно! пользователи могу обновить свою платежную информацию! Я не реализовал редактирование учетной записи. Это довольно просто, и пусть это останется упражнением для вас.Push-уведомления
В дополнение к возможностям для запроса API Recurly, сервис «ping» приложение с уведомлением, когда происходит какое-либо событие.Эти уведомления не следует путать с мобильного разнообразием, однако — они совершенно разные.По существу служба отправляет POST-запрос к URI, и посылает XML документ как тело запроса. Вы можете использовать библиотеки Recurly, что бы извлечь необходимую информацию, и действовать соответственно. Эти уведомления подробно описаны в документации Recurly.
Давайте определим нашу функцию обратного вызова, когда было получено уведомление:
Route: post ('recurly', function (){
$xml = file_get_contents («php://input»);
$notification = new Recurly_PushNotification ($xml);
switch ($notification→type) {
// … process notification
}
});
Вы, наверное, поняли, что, как только кто-то подписался и заплатил за услугу, он остается неопределенным подписчиком, и не понятно, продолжается ли их подписка или нет. Так, наибольший интерес представляет уведомление об отмене подписки. Мы можем использовать уведомление от Recurly, что бы определить неактивные подписки и отзывать соответствующие роли. Например:
switch ($notification→type) {
case 'canceled_subscription_notification':
// get the account code
$account_code = $notification→account→account_code;
// extract the user ID (account_code format is user_ID)
$user_id = intval (substr ($account_code, (strpos ($account_code, '_')+1)));
// find the user in question
$user = User: find ($user_id);
// get the plan code
$plan_code = $notification→subscription→plan→plan_code;
// find the corresponding role…
$role = Role: where ('name', '=', $plan_code)→first ();
// …and revoke it
DB: table ('role_user')→where ('user_id', '=', $user→id)→where ('role_id', '=', $role)→delete ();
break;
// … process notification
}
Есть целый ряд других вещей, которые вы могли бы сделать, в зависимости от типа уведомления.Вы можете использовать уведомления новый, обновленный, отменен, и т.д., чтобы создать историю подписки, отслеживать количество членов, и анализировать отказы. Вы также можете использовать уведомления о транзакции — будь то положительные (платежи) или отрицательные (возвраты) — отслеживать фактический и ожидаемый доход.
На этом оригинальная статья заканчивается. Спасибо всем, кто прочитал мою статью. Местами, я не понимал, что хочет сказать автор, вы поймете это при прочтении. Если вам будет интересен результат, то я выложу на гитхаб то, что получилось у меня (Сейчас, к сожалению не могу выложить — нет времени доделать практику по второй части). Спасибо за уделенное время!