From 165ecd0bf0f6c0ccbd6400b795222bc83bfcdfde Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Sun, 29 Nov 2015 22:13:50 +0200 Subject: [PATCH] Added support for Stripe.js --- app/Http/Controllers/AccountController.php | 15 +- .../Controllers/AccountGatewayController.php | 7 + app/Http/Controllers/PaymentController.php | 22 +- app/Listeners/HandleUserLoggedIn.php | 8 + app/Models/Account.php | 16 ++ app/Models/AccountGateway.php | 20 ++ app/Services/PaymentService.php | 12 +- resources/lang/da/texts.php | 1 - resources/lang/de/texts.php | 1 - resources/lang/en/texts.php | 8 +- resources/lang/es/texts.php | 1 - resources/lang/es_ES/texts.php | 1 - resources/lang/fr/texts.php | 1 - resources/lang/fr_CA/texts.php | 1 - resources/lang/it/texts.php | 1 - resources/lang/lt/texts.php | 1 - resources/lang/nb_NO/texts.php | 1 - resources/lang/nl/texts.php | 1 - resources/lang/pt_BR/texts.php | 1 - resources/lang/sv/texts.php | 1 - .../views/accounts/account_gateway.blade.php | 7 +- resources/views/clients/show.blade.php | 2 +- resources/views/payments/payment.blade.php | 203 ++++++------------ .../views/payments/payment_css.blade.php | 130 +++++++++++ 24 files changed, 288 insertions(+), 174 deletions(-) create mode 100644 resources/views/payments/payment_css.blade.php diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 05da6eea54..d7722136d2 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -212,13 +212,8 @@ class AccountController extends BaseController { // check that logo is less than the max file size $account = Auth::user()->account; - if ($account->hasLogo()) { - $filename = $account->getLogoPath(); - $bytes = File::size($filename); - if ($bytes > MAX_LOGO_FILE_SIZE * 1000) { - $bytes /= 1000; - Session::flash('warning', trans('texts.logo_too_large', ['size' => round($bytes) . 'KB'])); - } + if ($account->isLogoTooLarge()) { + Session::flash('warning', trans('texts.logo_too_large', ['size' => $account->getLogoSize() . 'KB'])); } $data = [ @@ -272,6 +267,12 @@ class AccountController extends BaseController $account->load('account_gateways'); $count = count($account->account_gateways); + if ($accountGateway = $account->getGatewayConfig(GATEWAY_STRIPE)) { + if ( ! $accountGateway->getPublishableStripeKey()) { + Session::flash('warning', trans('texts.missing_publishable_key')); + } + } + if ($count == 0) { return Redirect::to('gateways/create'); } else { diff --git a/app/Http/Controllers/AccountGatewayController.php b/app/Http/Controllers/AccountGatewayController.php index 56f8fd6623..d481e1b029 100644 --- a/app/Http/Controllers/AccountGatewayController.php +++ b/app/Http/Controllers/AccountGatewayController.php @@ -236,6 +236,13 @@ class AccountGatewayController extends BaseController } } + $publishableKey = Input::get('publishable_key'); + if ($publishableKey = str_replace('*', '', $publishableKey)) { + $config->publishableKey = $publishableKey; + } elseif ($oldConfig && property_exists($oldConfig, 'publishableKey')) { + $config->publishableKey = $oldConfig->publishableKey; + } + $cardCount = 0; if ($creditcards) { foreach ($creditcards as $card => $value) { diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php index 7ce213b523..69dec110fd 100644 --- a/app/Http/Controllers/PaymentController.php +++ b/app/Http/Controllers/PaymentController.php @@ -159,6 +159,7 @@ class PaymentController extends BaseController 'client' => $client, 'contact' => $invitation->contact, 'gateway' => $gateway, + 'accountGateway' => $accountGateway, 'acceptedCreditCardTypes' => $acceptedCreditCardTypes, 'countries' => Cache::get('countries'), 'currencyId' => $client->getCurrencyId(), @@ -340,12 +341,20 @@ class PaymentController extends BaseController $rules = [ 'first_name' => 'required', 'last_name' => 'required', - 'card_number' => 'required', - 'expiration_month' => 'required', - 'expiration_year' => 'required', - 'cvv' => 'required', ]; + if ( ! Input::get('stripeToken')) { + $rules = array_merge( + $rules, + [ + 'card_number' => 'required', + 'expiration_month' => 'required', + 'expiration_year' => 'required', + 'cvv' => 'required', + ] + ); + } + if ($accountGateway->show_address) { $rules = array_merge($rules, [ 'address1' => 'required', @@ -390,6 +399,11 @@ class PaymentController extends BaseController // check if we're creating/using a billing token if ($accountGateway->gateway_id == GATEWAY_STRIPE) { + if ($token = Input::get('stripeToken')) { + $details['token'] = $token; + unset($details['card']); + } + if ($useToken) { $details['customerReference'] = $client->getGatewayToken(); } elseif ($account->token_billing_type_id == TOKEN_BILLING_ALWAYS || Input::get('token_billing')) { diff --git a/app/Listeners/HandleUserLoggedIn.php b/app/Listeners/HandleUserLoggedIn.php index 5e65af0397..bf39d7e34e 100644 --- a/app/Listeners/HandleUserLoggedIn.php +++ b/app/Listeners/HandleUserLoggedIn.php @@ -45,6 +45,14 @@ class HandleUserLoggedIn { Session::put(SESSION_USER_ACCOUNTS, $users); $account->loadLocalizationSettings(); + + // if they're using Stripe make sure they're using Stripe.js + $accountGateway = $account->getGatewayConfig(GATEWAY_STRIPE); + if ($accountGateway && ! $accountGateway->getPublishableStripeKey()) { + Session::flash('warning', trans('texts.missing_publishable_key')); + } elseif ($account->isLogoTooLarge()) { + Session::flash('warning', trans('texts.logo_too_large', ['size' => $account->getLogoSize() . 'KB'])); + } } } diff --git a/app/Models/Account.php b/app/Models/Account.php index 41edf7d759..0842f36434 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -6,6 +6,7 @@ use Session; use DateTime; use Event; use App; +use File; use App\Events\UserSettingsChanged; use Illuminate\Database\Eloquent\SoftDeletes; use Laracasts\Presenter\PresentableTrait; @@ -581,6 +582,21 @@ class Account extends Eloquent } } + public function getLogoSize() + { + if (!$this->hasLogo()) { + return 0; + } + + $filename = $this->getLogoPath(); + return round(File::size($filename) / 1000); + } + + public function isLogoTooLarge() + { + return $this->getLogoSize() > MAX_LOGO_FILE_SIZE; + } + public function getSubscription($eventId) { return Subscription::where('account_id', '=', $this->id)->where('event_id', '=', $eventId)->first(); diff --git a/app/Models/AccountGateway.php b/app/Models/AccountGateway.php index e27a98d772..a4027db6ef 100644 --- a/app/Models/AccountGateway.php +++ b/app/Models/AccountGateway.php @@ -57,5 +57,25 @@ class AccountGateway extends EntityModel { return json_decode(Crypt::decrypt($this->config)); } + + public function getConfigField($field) + { + $config = $this->getConfig(); + + if (!$field || !property_exists($config, $field)) { + return false; + } + + return $config->$field; + } + + public function getPublishableStripeKey() + { + if ( ! $this->isGateway(GATEWAY_STRIPE)) { + return false; + } + + return $this->getConfigField('publishableKey'); + } } diff --git a/app/Services/PaymentService.php b/app/Services/PaymentService.php index 4d0d53841d..eee8c814f2 100644 --- a/app/Services/PaymentService.php +++ b/app/Services/PaymentService.php @@ -44,7 +44,9 @@ class PaymentService extends BaseService } $function = "set".ucfirst($key); - $gateway->$function($val); + if (method_exists($gateway, $function)) { + $gateway->$function($val); + } } if ($accountGateway->isGateway(GATEWAY_DWOLLA)) { @@ -100,10 +102,10 @@ class PaymentService extends BaseService $data = [ 'firstName' => $input['first_name'], 'lastName' => $input['last_name'], - 'number' => $input['card_number'], - 'expiryMonth' => $input['expiration_month'], - 'expiryYear' => $input['expiration_year'], - 'cvv' => $input['cvv'], + 'number' => isset($input['card_number']) ? $input['card_number'] : null, + 'expiryMonth' => isset($input['expiration_month']) ? $input['expiration_month'] : null, + 'expiryYear' => isset($input['expiration_year']) ? $input['expiration_year'] : null, + 'cvv' => isset($input['cvv']) ? $input['cvv'] : '', ]; if (isset($input['country_id'])) { diff --git a/resources/lang/da/texts.php b/resources/lang/da/texts.php index 6fa11cd5d2..6125f61374 100644 --- a/resources/lang/da/texts.php +++ b/resources/lang/da/texts.php @@ -447,7 +447,6 @@ 'gateway_help_1' => ':link til at registrere dig hos Authorize.net.', 'gateway_help_2' => ':link til at registrere dig hos Authorize.net.', 'gateway_help_17' => ':link til at hente din PayPal API signatur.', - 'gateway_help_23' => 'Note: brug din hemmelige API nøgle, IKKE din publicerede API nøgle.', 'gateway_help_27' => ':link til at registrere dig hos TwoCheckout.', 'more_designs' => 'Flere designs', diff --git a/resources/lang/de/texts.php b/resources/lang/de/texts.php index ff6a6da5ac..c2fe3e59ce 100644 --- a/resources/lang/de/texts.php +++ b/resources/lang/de/texts.php @@ -448,7 +448,6 @@ return array( 'gateway_help_1' => ':link um sich bei Authorize.net anzumelden.', 'gateway_help_2' => ':link um sich bei Authorize.net anzumelden.', 'gateway_help_17' => ':link um deine PayPal API-Signatur zu erhalten.', - 'gateway_help_23' => 'Anmerkung: benutze deinen secret API key, nicht deinen publishable API key.', 'gateway_help_27' => ':link um sich bei TwoCheckout anzumelden.', 'more_designs' => 'Weitere Designs', diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 771cea82ab..bee2302645 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -450,7 +450,6 @@ return array( 'gateway_help_1' => ':link to sign up for Authorize.net.', 'gateway_help_2' => ':link to sign up for Authorize.net.', 'gateway_help_17' => ':link to get your PayPal API signature.', - 'gateway_help_23' => 'Note: use your secret API key, not your publishable API key.', 'gateway_help_27' => ':link to sign up for TwoCheckout.', 'more_designs' => 'More designs', @@ -921,7 +920,7 @@ return array( 'country' => 'Country', 'include' => 'Include', - 'logo_too_large' => 'Your logo is :size, for better performance we suggest uploading an image file less than 200KB', + 'logo_too_large' => 'Your logo is :size, for better PDF performance we suggest uploading an image file less than 200KB', 'import_freshbooks' => 'Import From FreshBooks', 'import_data' => 'Import Data', 'source' => 'Source', @@ -950,4 +949,9 @@ return array( 'invoices_will_create' => 'invoices will be created', 'failed_to_import' => 'The following records failed to import', + 'publishable_key' => 'Publishable Key', + 'secret_key' => 'Secret Key', + 'missing_publishable_key' => 'Set your Stripe publishable key for an improved checkout process', + + ); diff --git a/resources/lang/es/texts.php b/resources/lang/es/texts.php index 0fb7664d7d..2b971743fe 100644 --- a/resources/lang/es/texts.php +++ b/resources/lang/es/texts.php @@ -420,7 +420,6 @@ return array( 'gateway_help_1' => ':link para registrarse con Authorize.net.', 'gateway_help_2' => ':link para registrarse con Authorize.net.', 'gateway_help_17' => ':link para obtener su firma del API de PayPal.', - 'gateway_help_23' => 'Nota: use use llave secreta del API, no la llave pública.', 'gateway_help_27' => ':link para registrarse con TwoCheckout.', 'more_designs' => 'Más diseños', diff --git a/resources/lang/es_ES/texts.php b/resources/lang/es_ES/texts.php index 4a6214f102..f71ab886a8 100644 --- a/resources/lang/es_ES/texts.php +++ b/resources/lang/es_ES/texts.php @@ -438,7 +438,6 @@ return array( 'gateway_help_1' => ':link para registrarse en Authorize.net.', 'gateway_help_2' => ':link para registrarse en Authorize.net.', 'gateway_help_17' => ':link para obtener su firma API de PayPal.', - 'gateway_help_23' => 'Nota: utilizar su clave de API secreta, no es su clave de API publica.', 'gateway_help_27' => ':link para registrarse en TwoCheckout.', 'more_designs' => 'Más diseños', diff --git a/resources/lang/fr/texts.php b/resources/lang/fr/texts.php index 22890d9b60..4fcc2a1c6e 100644 --- a/resources/lang/fr/texts.php +++ b/resources/lang/fr/texts.php @@ -441,7 +441,6 @@ return array( 'gateway_help_1' => ':link to sign up for Authorize.net.', 'gateway_help_2' => ':link to sign up for Authorize.net.', 'gateway_help_17' => ':link pour obtenir votre signature PayPal API.', - 'gateway_help_23' => 'Note: uutilisez votre Secret API et non votre clé publiable.', 'gateway_help_27' => ':link pour vous enregistrer sur TwoCheckout.', 'more_designs' => 'Plus de modèles', diff --git a/resources/lang/fr_CA/texts.php b/resources/lang/fr_CA/texts.php index 13d3e367d9..61cbe02727 100644 --- a/resources/lang/fr_CA/texts.php +++ b/resources/lang/fr_CA/texts.php @@ -441,7 +441,6 @@ return array( 'gateway_help_1' => ':link to sign up for Authorize.net.', 'gateway_help_2' => ':link to sign up for Authorize.net.', 'gateway_help_17' => ':link to get your PayPal API signature.', - 'gateway_help_23' => 'Note: use your secret API key, not your publishable API key.', 'gateway_help_27' => ':link to sign up for TwoCheckout.', 'more_designs' => 'Plus de modèles', diff --git a/resources/lang/it/texts.php b/resources/lang/it/texts.php index a35a42cbb2..ede5772c00 100644 --- a/resources/lang/it/texts.php +++ b/resources/lang/it/texts.php @@ -441,7 +441,6 @@ return array( 'gateway_help_1' => ':link to sign up for Authorize.net.', 'gateway_help_2' => ':link to sign up for Authorize.net.', 'gateway_help_17' => ':link to get your PayPal API signature.', - 'gateway_help_23' => 'Note: use your secret API key, not your publishable API key.', 'gateway_help_27' => ':link to sign up for TwoCheckout.', 'more_designs' => 'More designs', diff --git a/resources/lang/lt/texts.php b/resources/lang/lt/texts.php index 9aee3cd86e..bd71755ba9 100644 --- a/resources/lang/lt/texts.php +++ b/resources/lang/lt/texts.php @@ -449,7 +449,6 @@ return array( 'gateway_help_1' => ':link to sign up for Authorize.net.', 'gateway_help_2' => ':link to sign up for Authorize.net.', 'gateway_help_17' => ':link to get your PayPal API signature.', - 'gateway_help_23' => 'Note: use your secret API key, not your publishable API key.', 'gateway_help_27' => ':link to sign up for TwoCheckout.', 'more_designs' => 'More designs', diff --git a/resources/lang/nb_NO/texts.php b/resources/lang/nb_NO/texts.php index 3c50871fa6..74d6600a5d 100644 --- a/resources/lang/nb_NO/texts.php +++ b/resources/lang/nb_NO/texts.php @@ -447,7 +447,6 @@ return array( 'gateway_help_1' => ':link for å lage en konto for Authorize.net.', 'gateway_help_2' => ':link for å lage en konto for Authorize.net.', 'gateway_help_17' => ':link for å få din PayPal API signatur.', - 'gateway_help_23' => 'Info: bruk din hemmelige API nøkkel, ikke din offentlige API nøkkel.', 'gateway_help_27' => ':link for å lage en konto for TwoCheckout.', 'more_designs' => 'Flere design', diff --git a/resources/lang/nl/texts.php b/resources/lang/nl/texts.php index a071965d5e..bdcfe2480b 100644 --- a/resources/lang/nl/texts.php +++ b/resources/lang/nl/texts.php @@ -443,7 +443,6 @@ return array( 'gateway_help_1' => ':link om in te schrijven voor Authorize.net.', 'gateway_help_2' => ':link om in te schrijven voor Authorize.net.', 'gateway_help_17' => ':link om uw PayPal API signature te krijgen.', - 'gateway_help_23' => 'Opmerking: gebruik uw gehieme API key, niet uw publiceerbare API key.', 'gateway_help_27' => ':link om in te schrijven voor TwoCheckout.', 'more_designs' => 'Meer ontwerpen', diff --git a/resources/lang/pt_BR/texts.php b/resources/lang/pt_BR/texts.php index 0bd495921e..601c66c66f 100644 --- a/resources/lang/pt_BR/texts.php +++ b/resources/lang/pt_BR/texts.php @@ -441,7 +441,6 @@ return array( 'gateway_help_1' => ':link para acessar Authorize.net.', 'gateway_help_2' => ':link para acessar Authorize.net.', 'gateway_help_17' => ':link para adquirir sua "PayPal API signature".', - 'gateway_help_23' => 'Aviso: use sua "Secret API Key", não a "Publishable API Key".', 'gateway_help_27' => ':link para acessar TwoCheckout.', 'more_designs' => 'Mais Modelos', diff --git a/resources/lang/sv/texts.php b/resources/lang/sv/texts.php index 7401020eb6..c26d84775a 100644 --- a/resources/lang/sv/texts.php +++ b/resources/lang/sv/texts.php @@ -447,7 +447,6 @@ return array( 'gateway_help_1' => ':link för att registrera dig på Authorize.net.', 'gateway_help_2' => ':link för att registrera dig på Authorize.net.', 'gateway_help_17' => ':link för att hämta din PayPal API-nyckel.', - 'gateway_help_23' => 'Observera: använd din hemliga API-nyckel, inte den publika.', 'gateway_help_27' => ':link för att registrera dig för TwoCheckout.', 'more_designs' => 'Fler fakturalayouter', diff --git a/resources/views/accounts/account_gateway.blade.php b/resources/views/accounts/account_gateway.blade.php index dfb47aaf96..9c1f09cec3 100644 --- a/resources/views/accounts/account_gateway.blade.php +++ b/resources/views/accounts/account_gateway.blade.php @@ -19,8 +19,9 @@ {!! Former::populateField('gateway_id', $accountGateway->gateway_id) !!} {!! Former::populateField('payment_type_id', $paymentTypeId) !!} {!! Former::populateField('recommendedGateway_id', $accountGateway->gateway_id) !!} - {!! Former::populateField('show_address', intval($accountGateway->show_address)) !!} + {!! Former::populateField('show_address', intval($accountGateway->show_address)) !!} {!! Former::populateField('update_address', intval($accountGateway->update_address)) !!} + {!! Former::populateField('publishable_key', $accountGateway->getPublishableStripeKey() ? str_repeat('*', strlen($accountGateway->getPublishableStripeKey())) : '') !!} @if ($config) @foreach ($accountGateway->fields as $field => $junk) @@ -63,7 +64,7 @@ @elseif ($field == 'username' || $field == 'password') {!! Former::text($gateway->id.'_'.$field)->label('API '. ucfirst(Utils::toSpaceCase($field))) !!} @else - {!! Former::text($gateway->id.'_'.$field)->label(Utils::toSpaceCase($field)) !!} + {!! Former::text($gateway->id.'_'.$field)->label($gateway->id == GATEWAY_STRIPE ? trans('texts.secret_key') : Utils::toSpaceCase($field)) !!} @endif @endforeach @@ -78,6 +79,8 @@ @endif @if ($gateway->id == GATEWAY_STRIPE) + {!! Former::text('publishable_key') !!} + {!! Former::select('token_billing_type_id') ->options($tokenBillingOptions) ->help(trans('texts.token_billing_help')) !!} diff --git a/resources/views/clients/show.blade.php b/resources/views/clients/show.blade.php index b83bbb51f7..d6754ac6ba 100644 --- a/resources/views/clients/show.blade.php +++ b/resources/views/clients/show.blade.php @@ -322,7 +322,7 @@ if (!loadedTabs.hasOwnProperty(target)) { loadedTabs[target] = true; window['load_' + target](); - if (target == 'invoices') { + if (target == 'invoices' && window.hasOwnProperty('load_recurring_invoices')) { window['load_recurring_invoices'](); } } diff --git a/resources/views/payments/payment.blade.php b/resources/views/payments/payment.blade.php index d0b9831ade..e0961b5093 100644 --- a/resources/views/payments/payment.blade.php +++ b/resources/views/payments/payment.blade.php @@ -3,147 +3,66 @@ @section('head') @parent - + @if ($accountGateway->getPublishableStripeKey()) + + + @else + + @endif @stop @section('content') - +@include('payments.payment_css') {!! Former::vertical_open($url) ->autocomplete('on') + ->addClass('payment-form') ->rules(array( 'first_name' => 'required', 'last_name' => 'required', @@ -172,6 +91,8 @@ header h3 em {

 

+ +
@@ -279,14 +200,14 @@ header h3 em {

{{ trans('texts.billing_method') }}

- {!! Former::text($gateway->isGateway(GATEWAY_STRIPE) ? 'card_number' : 'card_number') + {!! Former::text($accountGateway->getPublishableStripeKey() ? '' : 'card_number') ->placeholder(trans('texts.card_number')) ->autocomplete('cc-number') ->data_stripe('number') ->label('') !!}
- {!! Former::text($gateway->isGateway(GATEWAY_STRIPE) ? 'cvv' : 'cvv') + {!! Former::text($accountGateway->getPublishableStripeKey() ? '' : 'cvv') ->placeholder(trans('texts.cvv')) ->autocomplete('off') ->data_stripe('cvc') @@ -295,7 +216,7 @@ header h3 em {
- {!! Former::select($gateway->isGateway(GATEWAY_STRIPE) ? 'expiration_month' : 'expiration_month') + {!! Former::select($accountGateway->getPublishableStripeKey() ? '' : 'expiration_month') ->autocomplete('cc-exp-month') ->data_stripe('exp-month') ->placeholder(trans('texts.expiration_month')) @@ -314,7 +235,7 @@ header h3 em { !!}
- {!! Former::select($gateway->isGateway(GATEWAY_STRIPE) ? 'expiration_year' : 'expiration_year') + {!! Former::select($accountGateway->getPublishableStripeKey() ? '' : 'expiration_year') ->autocomplete('cc-exp-year') ->data_stripe('exp-year') ->placeholder(trans('texts.expiration_year')) @@ -336,15 +257,15 @@ header h3 em {
- @if ($client && $account->showTokenCheckbox()) + @if ($client && $account->showTokenCheckbox()) selectTokenCheckbox() ? 'CHECKED' : '' }} value="1" style="margin-left:0px; vertical-align:top"> {!! trans('texts.token_billing_secure', ['stripe_link' => link_to('https://stripe.com/', 'Stripe.com', ['target' => '_blank'])]) !!} - @endif + @endif
-
- @if (isset($acceptedCreditCardTypes)) +
+ @if (isset($acceptedCreditCardTypes))
@foreach ($acceptedCreditCardTypes as $card) {{ $card['alt'] }} diff --git a/resources/views/payments/payment_css.blade.php b/resources/views/payments/payment_css.blade.php new file mode 100644 index 0000000000..e22a154645 --- /dev/null +++ b/resources/views/payments/payment_css.blade.php @@ -0,0 +1,130 @@ +