From 401851e212310de8f072bd440a58f14328b364be Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Tue, 12 Jul 2016 23:46:41 +0300 Subject: [PATCH] Working on buy now buttons --- CHANGELOG.md | 7 +- app/Http/Controllers/AccountController.php | 11 ++ .../Controllers/OnlinePaymentController.php | 59 ++++++++ app/Http/Middleware/VerifyCsrfToken.php | 2 +- app/Http/routes.php | 1 + .../PaymentDrivers/BasePaymentDriver.php | 9 +- app/Services/PaymentService.php | 16 --- resources/lang/en/texts.php | 9 +- .../views/accounts/client_portal.blade.php | 136 +++++++++++++++++- .../views/payments/credit_card.blade.php | 18 ++- 10 files changed, 234 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50c1739ad6..813bbb4c11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,12 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -## [2.6] - 2016-07-08 +## [Unreleased] + +### Added +- Added 'Buy Now' buttons + +## [2.6] - 2016-07-12 ### Added - Configuration for first day of the week #950 diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 52b451d8b1..9e6f058c81 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -25,6 +25,7 @@ use App\Models\Document; use App\Models\Gateway; use App\Models\InvoiceDesign; use App\Models\TaxRate; +use App\Models\Product; use App\Models\PaymentTerm; use App\Ninja\Repositories\AccountRepository; use App\Ninja\Repositories\ReferralRepository; @@ -714,6 +715,14 @@ class AccountController extends BaseController ); } + $types = [GATEWAY_TYPE_CREDIT_CARD, GATEWAY_TYPE_BANK_TRANSFER, GATEWAY_TYPE_PAYPAL, GATEWAY_TYPE_BITCOIN, GATEWAY_TYPE_DWOLLA]; + $options = []; + foreach ($types as $type) { + if ($account->getGatewayByType($type)) { + $options[$type] = trans("texts.{$type}"); + } + } + $data = [ 'client_view_css' => $css, 'enable_portal_password' => $account->enable_portal_password, @@ -721,6 +730,8 @@ class AccountController extends BaseController 'title' => trans('texts.client_portal'), 'section' => ACCOUNT_CLIENT_PORTAL, 'account' => $account, + 'products' => Product::scope()->orderBy('product_key')->get(), + 'gateway_types' => $options, ]; return View::make('accounts.client_portal', $data); diff --git a/app/Http/Controllers/OnlinePaymentController.php b/app/Http/Controllers/OnlinePaymentController.php index 60483bf7b2..da227f6c74 100644 --- a/app/Http/Controllers/OnlinePaymentController.php +++ b/app/Http/Controllers/OnlinePaymentController.php @@ -4,14 +4,20 @@ use Session; use Input; use Utils; use View; +use Auth; +use URL; use Exception; +use Validator; use App\Models\Invitation; use App\Models\Account; use App\Models\Payment; +use App\Models\Product; use App\Models\PaymentMethod; use App\Services\PaymentService; use App\Ninja\Mailers\UserMailer; use App\Http\Requests\CreateOnlinePaymentRequest; +use App\Ninja\Repositories\ClientRepository; +use App\Services\InvoiceService; /** * Class OnlinePaymentController @@ -203,4 +209,57 @@ class OnlinePaymentController extends BaseController } } + public function handleBuyNow(ClientRepository $clientRepo, InvoiceService $invoiceService, $gatewayType = false) + { + $account = Account::whereAccountKey(Input::get('account_key'))->first(); + $redirectUrl = Input::get('redirect_url', URL::previous()); + + if ( ! $account) { + return redirect()->to("{$redirectUrl}/?error=invalid account"); + } + + Auth::onceUsingId($account->users[0]->id); + $product = Product::scope(Input::get('product_id'))->first(); + + if ( ! $product) { + return redirect()->to("{$redirectUrl}/?error=invalid product"); + } + + $rules = [ + 'first_name' => 'string|max:100', + 'last_name' => 'string|max:100', + 'email' => 'email|string|max:100', + ]; + + $validator = Validator::make(Input::all(), $rules); + if ($validator->fails()) { + return redirect()->to("{$redirectUrl}/?error=" . $validator->errors()->first()); + } + + $data = [ + 'contact' => Input::all() + ]; + $client = $clientRepo->save($data); + + $data = [ + 'client_id' => $client->public_id, + 'invoice_items' => [[ + 'product_key' => $product->product_key, + 'notes' => $product->notes, + 'cost' => $product->cost, + 'qty' => 1, + 'tax_rate1' => $product->default_tax_rate ? $product->default_tax_rate->rate : 0, + 'tax_name1' => $product->default_tax_rate ? $product->default_tax_rate->name : '', + ]] + ]; + $invoice = $invoiceService->save($data); + $invitation = $invoice->invitations[0]; + $link = $invitation->getLink(); + + if ($gatewayType) { + return redirect()->to($invitation->getLink('payment') . "/{$gatewayType}"); + } else { + return redirect()->to($invitation->getLink()); + } + } } diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php index 90ca57627a..43456eaf6f 100644 --- a/app/Http/Middleware/VerifyCsrfToken.php +++ b/app/Http/Middleware/VerifyCsrfToken.php @@ -30,6 +30,7 @@ class VerifyCsrfToken extends BaseVerifier 'hook/email_bounced', 'reseller_stats', 'payment_hook/*', + 'buy_now/*', ]; /** @@ -42,7 +43,6 @@ class VerifyCsrfToken extends BaseVerifier public function handle($request, Closure $next) { foreach ($this->openRoutes as $route) { - if ($request->is($route)) { return $next($request); } diff --git a/app/Http/routes.php b/app/Http/routes.php index 7bd65e479d..195b1b0374 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -81,6 +81,7 @@ Route::post('signup/submit', 'AccountController@submitSignup'); Route::get('/auth/{provider}', 'Auth\AuthController@authLogin'); Route::get('/auth_unlink', 'Auth\AuthController@authUnlink'); +Route::match(['GET', 'POST'], '/buy_now/{gateway_type?}', 'OnlinePaymentController@handleBuyNow'); Route::post('/hook/email_bounced', 'AppController@emailBounced'); Route::post('/hook/email_opened', 'AppController@emailOpened'); diff --git a/app/Ninja/PaymentDrivers/BasePaymentDriver.php b/app/Ninja/PaymentDrivers/BasePaymentDriver.php index 17ed76d3fc..0e906ed558 100644 --- a/app/Ninja/PaymentDrivers/BasePaymentDriver.php +++ b/app/Ninja/PaymentDrivers/BasePaymentDriver.php @@ -227,7 +227,7 @@ class BasePaymentDriver $gateway = $this->gateway(); if ($input) { - $this->updateAddress(); + $this->updateClient(); } // load or create token @@ -280,8 +280,13 @@ class BasePaymentDriver } } - private function updateAddress() + private function updateClient() { + if ( ! $this->contact()->email && $this->input['email']) { + $this->contact()->email = $this->input['email']; + $this->contact()->save(); + } + if ( ! $this->isGatewayType(GATEWAY_TYPE_CREDIT_CARD)) { return; } diff --git a/app/Services/PaymentService.php b/app/Services/PaymentService.php index 107fec533d..4c58f62f46 100644 --- a/app/Services/PaymentService.php +++ b/app/Services/PaymentService.php @@ -12,21 +12,6 @@ use App\Ninja\Datatables\PaymentDatatable; class PaymentService extends BaseService { - /** - * @var DatatableService - */ - protected $datatableService; - - /** - * @var PaymentRepository - */ - protected $paymentRepo; - - /** - * @var AccountRepository - */ - protected $accountRepo; - /** * PaymentService constructor. * @@ -157,5 +142,4 @@ class PaymentService extends BaseService return parent::bulk($ids, $action); } } - } diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 4038ee96a2..e8b9bae275 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -2027,7 +2027,14 @@ $LANG = array( 'restored_expense_category' => 'Successfully restored expense category', 'apply_taxes' => 'Apply taxes', 'min_to_max_users' => ':min to :max users', - 'max_users_reached' => 'The maximum number of users has been reached.' + 'max_users_reached' => 'The maximum number of users has been reached.', + 'buy_now_buttons' => 'Buy Now Buttons', + 'landing_page' => 'Landing Page', + 'payment_type' => 'Payment Type', + 'form' => 'Form', + 'link' => 'Link', + 'fields' => 'Fields', + 'buy_now_buttons_warning' => 'Note: client and invoice records are created even if the transaction isn\'t completed.', ); diff --git a/resources/views/accounts/client_portal.blade.php b/resources/views/accounts/client_portal.blade.php index 1488390183..daf1efa259 100644 --- a/resources/views/accounts/client_portal.blade.php +++ b/resources/views/accounts/client_portal.blade.php @@ -3,7 +3,16 @@ @section('head') @parent - + @include('money_script') + + + + + @stop @section('content') @@ -69,6 +78,65 @@ +
+
+

{!! trans('texts.buy_now_buttons') !!}

+
+
+
+ + {!! Former::select('product') + ->onchange('updateBuyNowButtons()') + ->addOption('', '') + ->inlineHelp('buy_now_buttons_warning') + ->addGroupClass('product-select') !!} + + {!! Former::inline_checkboxes('client_fields') + ->onchange('updateBuyNowButtons()') + ->checkboxes([ + trans('texts.first_name') => ['value' => 'first_name', 'name' => 'first_name'], + trans('texts.last_name') => ['value' => 'last_name', 'name' => 'last_name'], + trans('texts.email') => ['value' => 'email', 'name' => 'email'], + ]) !!} + + {!! Former::inline_radios('landing_page') + ->onchange('showPaymentTypes();updateBuyNowButtons();') + ->radios([ + trans('texts.invoice') => ['value' => 'invoice', 'name' => 'landing_page_type'], + trans('texts.payment') => ['value' => 'payment', 'name' => 'landing_page_type'], + ])->check('invoice') !!} + + + +

 

+ +
+ +
+
+
+ +
+ +
+ +
+
+
+ @if (Utils::hasFeature(FEATURE_CLIENT_PORTAL_CSS))
@@ -95,12 +163,74 @@ {!! Former::close() !!} + + @stop diff --git a/resources/views/payments/credit_card.blade.php b/resources/views/payments/credit_card.blade.php index a9c3f89e90..b60f992591 100644 --- a/resources/views/payments/credit_card.blade.php +++ b/resources/views/payments/credit_card.blade.php @@ -77,16 +77,14 @@
- @if (isset($paymentTitle) || ! empty($contact->email)) -
-
- {!! Former::text('email') - ->placeholder(trans('texts.email')) - ->autocomplete('email') - ->label('') !!} -
+
+
+ {!! Former::text('email') + ->placeholder(trans('texts.email')) + ->autocomplete('email') + ->label('') !!}
- @endif +

 
 

@@ -257,5 +255,5 @@

 

{!! Former::close() !!} - + @stop