Планирование и обработка платеже это легко, но не так легок прием регулярных платежей. Сложности могут возникнуть очень быстро. Вы должны решить, как обрабатывать отказы, данные о платежах должны быть постоянно актуальны, и поддерживать актуальность данных на сайте. И пожалуй, самый важный вопрос — держать своих пользователей в курсе платежной информации на сайте.
К счастью, Recurly — это сервис, который выполняет большую часть задач, связанных с обработкой регулярных платежей. Используя JavaScript-библиотеки, вы сможете создавать защищенные формы для отправки и обновления платежной информации, включающие в себя все важные данные платежной карты.
После того, как вы определили сумму и частоту платежей, Recurly заботится о расписании и принятии платежей, до тех пор, пока клиент не будет отписан. Recurly, также учитывает изменения тарифных планов, расчетов, внесении и вычетов дополнительных платежей.
В первой статье из двух, я покажу Вам как создать платную подписку используя сайт, созданный с использование php-фреймворка Laravel и сервиса приема платежей Recurly. Мы начнём с создания сайта с простой регистрацией, авторизацией и правами пользователя. Затем мы добавим обработку платежей, свяжем её с процессом регистрации, что позволит пользователям покупать различные тарифные планы.
Установка приложения.
Начнём создания приложения с создания новой папки для проекта и запуском следующей команды:
composer create-project laravel/laravel recurly --prefer-dist
Эта команда создаст новое приложение Laravel, использую Composer, скачает фреймворк и все необходимые зависимости. Позже нам понадобятся несколько библиотек, поэтому добавьте следующие строки в composer.json и запустите composer.phar update
"machuga/authority": "dev-develop",
"machuga/authority-l4" : "dev-master",
"recurly/recurly-client": "2.1.*@dev"
Будет скачана библиотека Authority, которая будет использована для создания ролей пользователей и прав доступа, и библиотека Recurly.
Затем, необходимо настроить соединение с БД указав значение схемы, пользователя, пароля и адресс к БД в файле app/config/database.php. Laravel работает «из коробки» со следующими базами данных: MySql, Posrges, SQLite и SQL Server.
Нам так же необходима будет таблица с пользователями. Вместо того, что бы делать всё «руками», используем механизм миграций, предоставляемый Laravel. Выполните следующую команду:
php artisan migrate:make create_users_table
Эта команда создаст файл миграции в папке app/database/migrations
public function up()
{
Schema::create('users', function($table) {
$table->increments('id');
$table->string('email')->unique();
$table->string('name');
$table->string('password');
$table->timestamps();
});
}
public function down()
{
Schema::drop('users');
}
Вернемся к командной строке и выполним:
php artisan migrate
Посмотрим в базе данных и увидим что Laravel создал таблицу с пользователями.
Создадим роли пользователей и права.
Для определения типа пользователя и прав для этого пользователя, мы установим пользователям роли. Мы уже скачали библиотеку Authoriry с помощью composer, и сейчас мы должны выполнить ещё несколько шагов для настройки ролей полностью.
В файле app/config/app.php добавьте следующую строку:
'AuthorityAuthorityL4AuthorityL4ServiceProvider',
Добавьте следующую строку к алиасам:
'Authority' => 'AuthorityAuthorityL4FacadesAuthority',
и опубликуйте файл настроек Authority следующей командой:
php artisan config:publish machuga/authority-l4
Вернемся к файлу настроек позже. А сейчас, мы должны создать несколько дополнительных таблиц в БД. К счастью, Laravel содержит собственные миграции для них. Запустим их следующей командой:
php artisan migrate --package="machuga/authority-l4"
Вы увидите что создалось 3 дополнительных таблицы: permissions, roles, role_user.
Теперь нам необходимо создать модель для работы с ролями и правами доступа. Пока мы их не будем изменять и оставим очень простыми. В app/models/Role.php:
<?php
class Role extends Eloquent
{
}
В файле: app/models/Permission.php:
<?php
class Permission extends Eloquent
{
}
Сейчас мы должны изменить модель User, она уже была создана, а мы добавим связь пользователей с их ролями и правами доступа. Добавьте следующие строки в app/models/User.php:
public function roles() {
return $this->belongsToMany('Role');
}
public function permissions() {
return $this->hasMany('Permission');
}
public function hasRole($key) {
foreach($this->roles as $role){
if ($role->name === $key) {
return true;
}
}
return false;
}
А теперь заполним базу данных некоторым данными. Откройте файл app/database/seeds/DatabaseSeeder.php и вставьте следующее:
<?php
class DatabaseSeeder extends Seeder
{
public function run() {
Eloquent::unguard();
$this->call('UserTableSeeder');
$this->command->info('User table seeded!');
$this->call('RoleTableSeeder');
$this->command->info('Role table seeded!');
}
}
class UserTableSeeder extends Seeder
{
public function run() {
DB::table('users')->delete();
User::create(array(
'email' => 'joe.bloggs@example.com',
'name' => 'Joe Bloggs',
'password' => Hash::make('password')
));
}
}
class RoleTableSeeder extends Seeder
{
public function run() {
DB::table('roles')->delete();
Role::create(array('name' => 'admin'));
Role::create(array('name' => 'pending'));
Role::create(array('name' => 'member'));
Role::create(array('name' => 'bronze'));
Role::create(array('name' => 'silver'));
Role::create(array('name' => 'gold'));
}
}
Далее заполним базу данных, выполнив следующую команду:
php artisan db:seed
Создаём шаблон
Сейчас мы создадим общий шаблон для страниц. Скачаем для этого Twitter Bootstrap и положим исходники в папку public, а js-файлы в папку — public/js/libs/
Создадим файл app/views/layouts/default.blade.php со следующим кодом:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Subscription Site Tutorial</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<!-- Le styles -->
<link href="/css/bootstrap.css" rel="stylesheet">
<link href="/css/style.css" rel="stylesheet">
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="brand" href="#">Subscription Site Tutorial</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</div>
<div class="container">
@if(Session::has('success'))
<div class="alert alert-success">
<button type="button" class="close" data-dismiss="alert">×</button>
{{ Session::get('success') }}
</div>
@endif
@if(Session::has('error'))
<div class="alert alert-error">
<button type="button" class="close" data-dismiss="alert">×</button>
{{ Session::get('error') }}
</div>
@endif
@yield('content')
</div> <!-- /container -->
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="/js/libs/bootstrap.min.js"></script>
</body>
</html>
Это базовый шаблон для нашего сайта, контент страницы будет выводиться в строке yield('content').
Далее, создадим файл public/css/style.css:
body {
padding-top: 50px;
}
p.logged-in {
color: white;
margin-top: 0.5em;
}
И наконец, создадим главную страницу нашего сайта. Создайте файл app/views/home/index.blade.php:
@extends('layouts.default')
@section('content')
<h1>Subscription Site Tutorial</h1>
@stop
@extends говорит Laravel, что надо использовать шаблон по-умолчанию, который мы только что создали.
Не забудем изменить роутинг нашего сайта в файле app/routes.php:
Route::get('/', function() {
return View::make('home/index');
});
Создаём механизм авторизации
У нас есть пользователи, и теперь мы должны дать им возможность авторизации. В файле app/routse.php, добавим путь к странице входа:
Route::get('/auth/login', function() {
return View::make('auth/login');
});
Сейчас мы создадим отображение в файле app/views/auth/login.blade.php. .blacde означает что мы используем шаблонизатор Blade, идущий вместе с Laravel.
@extends('layouts.default')
@section('content')
<h1>Please Log in</h1>
{{ Form::open(array('url' => 'auth/login')) }}
{{ Form::label('email', 'E-Mail Address') }}
{{ Form::text('email') }}
{{ Form::label('password', 'Password') }}
{{ Form::password('password') }}
<div class="form-actions">
{{ Form::submit('Login', array('class' => 'btn btn-primary')) }}
</div>
{{ Form::close() }}
<p>Not a member? <a href="/user/register">Register here</a>.</p>
@stop
Если вы перейдете по адрес /auth/logn вы увидите простую форму входа. Для обработки входа, мы должны будем обработать POST данные. Авторизация в Laravel проста:
Route::post('/auth/login', function() {
$email = Input::get('email');
$password = Input::get('password');
if (Auth::attempt(array('email' => $email, 'password' => $password))) {
return Redirect::to('/')->with('success', 'You have been logged in');
}
else {
return Redirect::to('auth/login')->with('error', 'Login Failed');
}
return View::make('auth/login');
});
Вся магия находится в методе Auth::attempt(), если авторизация успешна создаётся сессия и экземпляр объекта User, доступны через статичный метод Auth::user()
Метод выхода из аккаунта:
Route::get('/auth/logout', function() {
Auth::logout();
return Redirect::to('/')->with('success', 'You have successfully logged out');
});
Базовая регистрация
Нашей последней задачей, в этой части, является создание процесса регистрации. Создадим путь для регистрации в файле app/routse/php:
Route::get('/user/register', function() {
return View::make('user/register/index');
});
Создадим представление в файле /app/views/user/register/index.blade.php:
@extends('layouts.default')
@section('content')
{{ Form::open(array('url' => 'user/register')) }}
{{ Form::label('email', 'E-Mail Address') }}
{{ Form::text('email') }}
{{ $errors->first('email') }}
{{ Form::label('name', 'Your name') }}
{{ Form::text('name') }}
{{ $errors->first('name') }}
{{ Form::label('password', 'Password') }}
{{ Form::password('password') }}
{{ $errors->first('password') }}
{{ Form::label('password_confirmation', 'Repeat') }}
{{ Form::password('password_confirmation') }}
<div class="form-actions">
{{ Form::submit('Register', array('class' => 'btn btn-primary')) }}
</div>
{{ Form::close() }}
@stop
Отмечу несколько моментов:
- Объект $error передаётся в представлении автоматически, и если нет ошибок валидации, то соответствующее поле будет пустым
- Суффикс _confirmation означает что поле должно соответствовать полю без суффикса, т.е. для проверки, что пароль оба раза был введен корректно
Теперь перейдём к обработке POST данных:
Route::post('/user/register', function() {
$validator = Validator::make(
Input::all(),
array(
'name' => array('required', 'min:5'),
'email' => array('required', 'email', 'unique:users'),
'password' => array('required', 'confirmed')
)
);
if ($validator->passes()) {
$user = new User();
$user->name = Input::get('name');
$user->email = Input::get('email');
$user->password = Hash::make(Input::get('password'));
$user->save();
$role_pending = Role::where('name', '=', 'pending')->first();
$user->roles()->attach($role_pending);
Auth::login($user);
return Redirect::to('/')->with(
'success',
'Welcome to the site, . Auth::user()->name . '!'
);
}
else {
return Redirect::to('user/register')->with(
'error',
'Please correct the following errors:'
)->withErrors($validator);
}
});
Это достаточно простой способ. Мы создаём валидатор и передаём ему POST данные (Input::all()) и определяем правила для валидации. Если валидация прошла, ты мы создаём нового пользователя, назначаем ему роли, авторизуем, и перенаправляем его на главную страницу.
Если валидация завершилась ошибкой, то мы редиректим пользователя обратно на форму, создаём сообщение об ошибке, и передаём сообщения об ошибках от валидатора, которые будут доступны из представления в переменной $errors.
Заключение
В этой части мы шаг за шагом создавали «скелет» приложения, для работы с платными подписками. В следующей части мы будем интегрировать Recurly для использования подписок.
Автор: WildZero
Спасибо! Долго искал как пользоваться стандартным шаблонизатором