Создаём сайт, используя Laravel и Recurly

от автора

Планирование и обработка платеже это легко, но не так легок прием регулярных платежей. Сложности могут возникнуть очень быстро. Вы должны решить, как обрабатывать отказы, данные о платежах должны быть постоянно актуальны, и поддерживать актуальность данных на сайте. И пожалуй, самый важный вопрос — держать своих пользователей в курсе платежной информации на сайте.
К счастью, 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 добавьте следующую строку:

'Authority\AuthorityL4\AuthorityL4ServiceProvider', 

Добавьте следующую строку к алиасам:

'Authority' => 'Authority\AuthorityL4\Facades\Authority', 

и опубликуйте файл настроек 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 для использования подписок.

ссылка на оригинал статьи http://habrahabr.ru/post/195690/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *