From 7f27abace2ad5fb06dff9b08deaf8eb501967c8d Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Wed, 18 Feb 2015 00:22:12 +0200 Subject: [PATCH] Added support for Stripe token billing --- app/controllers/AccountController.php | 27 ++++++++- app/controllers/ClientController.php | 1 + app/controllers/InvoiceController.php | 1 + app/controllers/PaymentController.php | 46 ++++++++++++--- ...015_02_17_131714_support_token_billing.php | 56 +++++++++++++++++++ app/lang/da/texts.php | 13 +++++ app/lang/de/texts.php | 15 ++++- app/lang/en/texts.php | 14 +++++ app/lang/es/texts.php | 13 +++++ app/lang/fr/texts.php | 13 +++++ app/lang/it/texts.php | 13 +++++ app/lang/lt/texts.php | 13 +++++ app/lang/nb_NO/texts.php | 13 +++++ app/lang/nl/texts.php | 15 ++++- app/lang/pt_BR/texts.php | 13 +++++ app/models/Account.php | 11 ++++ app/models/AccountGatewayToken.php | 7 +++ app/models/Client.php | 27 +++++++++ app/routes.php | 5 ++ app/views/accounts/payments.blade.php | 8 ++- app/views/clients/show.blade.php | 4 ++ app/views/invoices/pdf.blade.php | 2 +- app/views/invoices/view.blade.php | 9 ++- app/views/payments/payment.blade.php | 10 +++- 24 files changed, 332 insertions(+), 17 deletions(-) create mode 100644 app/database/migrations/2015_02_17_131714_support_token_billing.php create mode 100644 app/models/AccountGatewayToken.php diff --git a/app/controllers/AccountController.php b/app/controllers/AccountController.php index cceb1853bb..70e1cbb639 100755 --- a/app/controllers/AccountController.php +++ b/app/controllers/AccountController.php @@ -184,6 +184,11 @@ class AccountController extends \BaseController } } + $tokenBillingOptions = []; + for ($i=1; $i<=4; $i++) { + $tokenBillingOptions[$i] = trans("texts.token_billing_{$i}"); + } + $data = [ 'account' => $account, 'accountGateway' => $accountGateway, @@ -195,7 +200,8 @@ class AccountController extends \BaseController ->orderBy('name') ->get(), 'recommendedGateways' => $recommendedGatewayArray, - 'creditCardTypes' => $creditCards, + 'creditCardTypes' => $creditCards, + 'tokenBillingOptions' => $tokenBillingOptions, ]; return View::make('accounts.payments', $data); @@ -663,10 +669,22 @@ class AccountController extends \BaseController } } - if ($isMasked && count($account->account_gateways)) { + // check if a gateway is already configured + $currentGateway = false; + if (count($account->account_gateways)) { $currentGateway = $account->account_gateways[0]; + } + + // if the values haven't changed don't update the config + if ($isMasked && $currentGateway) { $currentGateway->accepted_credit_cards = $cardCount; $currentGateway->save(); + // if there's an existing config for this gateway update it + } elseif (!$isMasked && $currentGateway && $currentGateway->gateway_id == $gatewayId) { + $currentGateway->accepted_credit_cards = $cardCount; + $currentGateway->config = json_encode($config); + $currentGateway->save(); + // otherwise, create a new gateway config } else { $accountGateway->config = json_encode($config); $accountGateway->accepted_credit_cards = $cardCount; @@ -675,6 +693,11 @@ class AccountController extends \BaseController $account->account_gateways()->save($accountGateway); } + if (Input::get('token_billing_type_id')) { + $account->token_billing_type_id = Input::get('token_billing_type_id'); + $account->save(); + } + Session::flash('message', trans('texts.updated_settings')); } else { Session::flash('error', trans('validation.required', ['attribute' => 'gateway'])); diff --git a/app/controllers/ClientController.php b/app/controllers/ClientController.php index ea697d1853..a06b6c5bdc 100755 --- a/app/controllers/ClientController.php +++ b/app/controllers/ClientController.php @@ -106,6 +106,7 @@ class ClientController extends \BaseController 'credit' => $client->getTotalCredit(), 'title' => trans('texts.view_client'), 'hasRecurringInvoices' => Invoice::scope()->where('is_recurring', '=', true)->whereClientId($client->id)->count() > 0, + 'gatewayLink' => $client->getGatewayLink(), ); return View::make('clients.show', $data); diff --git a/app/controllers/InvoiceController.php b/app/controllers/InvoiceController.php index 11dd20b304..884e26efd8 100755 --- a/app/controllers/InvoiceController.php +++ b/app/controllers/InvoiceController.php @@ -177,6 +177,7 @@ class InvoiceController extends \BaseController 'invitation' => $invitation, 'invoiceLabels' => $client->account->getInvoiceLabels(), 'contact' => $contact, + 'hasToken' => $client->getGatewayToken() ); return View::make('invoices.view', $data); diff --git a/app/controllers/PaymentController.php b/app/controllers/PaymentController.php index 606ba6f897..ff4668c0b4 100755 --- a/app/controllers/PaymentController.php +++ b/app/controllers/PaymentController.php @@ -287,14 +287,16 @@ class PaymentController extends \BaseController public function show_payment($invitationKey) { + // Handle token billing + if (Input::get('use_token') == 'true') { + return self::do_payment($invitationKey, false, true); + } // For PayPal Express we redirect straight to their site $invitation = Invitation::with('invoice.client.account', 'invoice.client.account.account_gateways.gateway')->where('invitation_key', '=', $invitationKey)->firstOrFail(); $account = $invitation->invoice->client->account; - if ($account->isGatewayConfigured(GATEWAY_PAYPAL_EXPRESS)) { if (Session::has('error')) { Session::reflash(); - return Redirect::to('view/'.$invitationKey); } else { return self::do_payment($invitationKey, false); @@ -321,6 +323,7 @@ class PaymentController extends \BaseController 'acceptedCreditCardTypes' => $acceptedCreditCardTypes, 'countries' => Country::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(), 'currencyId' => $client->currency_id, + 'account' => $client->account ]; return View::make('payments.payment', $data); @@ -486,7 +489,7 @@ class PaymentController extends \BaseController } } - public function do_payment($invitationKey, $onSite = true) + public function do_payment($invitationKey, $onSite = true, $useToken = false) { $rules = array( 'first_name' => 'required', @@ -512,11 +515,12 @@ class PaymentController extends \BaseController $invitation = Invitation::with('invoice.invoice_items', 'invoice.client.currency', 'invoice.client.account.account_gateways.gateway')->where('invitation_key', '=', $invitationKey)->firstOrFail(); $invoice = $invitation->invoice; - $accountGateway = $invoice->client->account->account_gateways[0]; + $client = $invoice->client; + $account = $client->account; + $accountGateway = $account->account_gateways[0]; $paymentLibrary = $accountGateway->gateway->paymentlibrary; if ($onSite) { - $client = $invoice->client; $client->address1 = trim(Input::get('address1')); $client->address2 = trim(Input::get('address2')); $client->city = trim(Input::get('city')); @@ -528,7 +532,32 @@ class PaymentController extends \BaseController try { if ($paymentLibrary->id == PAYMENT_LIBRARY_OMNIPAY) { $gateway = self::createGateway($accountGateway); - $details = self::getPaymentDetails($invoice, Input::all()); + $details = self::getPaymentDetails($invoice, $useToken ? false : Input::all()); + + if ($accountGateway->gateway_id == GATEWAY_STRIPE) { + if ($useToken) { + $details['cardReference'] = $client->getGatewayToken(); + } elseif ($account->token_billing_type_id == TOKEN_BILLING_ALWAYS || Input::get('token_billing')) { + $tokenResponse = $gateway->createCard($details)->send(); + $cardReference = $tokenResponse->getCardReference(); + $details['cardReference'] = $cardReference; + + $token = AccountGatewayToken::where('client_id', '=', $client->id) + ->where('account_gateway_id', '=', $accountGateway->id)->first(); + + if (!$token) { + $token = new AccountGatewayToken(); + $token->account_id = $account->id; + $token->contact_id = $invitation->contact_id; + $token->account_gateway_id = $accountGateway->id; + $token->client_id = $client->id; + } + + $token->token = $cardReference; + $token->save(); + } + } + $response = $gateway->purchase($details)->send(); $ref = $response->getTransactionReference(); @@ -541,7 +570,6 @@ class PaymentController extends \BaseController if ($response->isSuccessful()) { $payment = self::createPayment($invitation, $ref); - Session::flash('message', trans('texts.applied_payment')); return Redirect::to('view/'.$payment->invitation->invitation_key); @@ -693,12 +721,14 @@ class PaymentController extends \BaseController ->withInput(); } else { $this->paymentRepo->save($publicId, Input::all()); - + if ($publicId) { Session::flash('message', trans('texts.updated_payment')); + return Redirect::to('payments/'); } else { Session::flash('message', trans('texts.created_payment')); + return Redirect::to('clients/'.Input::get('client')); } } diff --git a/app/database/migrations/2015_02_17_131714_support_token_billing.php b/app/database/migrations/2015_02_17_131714_support_token_billing.php new file mode 100644 index 0000000000..0022d44cf2 --- /dev/null +++ b/app/database/migrations/2015_02_17_131714_support_token_billing.php @@ -0,0 +1,56 @@ +smallInteger('token_billing_type_id')->default(TOKEN_BILLING_OPT_IN); + }); + + Schema::create('account_gateway_tokens', function($table) + { + $table->increments('id'); + $table->unsignedInteger('account_id'); + $table->unsignedInteger('contact_id'); + $table->unsignedInteger('account_gateway_id'); + $table->unsignedInteger('client_id'); + $table->string('token'); + + $table->timestamps(); + $table->softDeletes(); + + $table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); + $table->foreign('contact_id')->references('id')->on('contacts')->onDelete('cascade'); + $table->foreign('account_gateway_id')->references('id')->on('account_gateways')->onDelete('cascade'); + $table->foreign('client_id')->references('id')->on('clients')->onDelete('cascade'); + }); + + DB::table('accounts')->update(['token_billing_type_id' => TOKEN_BILLING_OPT_IN]); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('accounts', function($table) + { + $table->dropColumn('token_billing_type_id'); + }); + + Schema::drop('account_gateway_tokens'); + } + +} \ No newline at end of file diff --git a/app/lang/da/texts.php b/app/lang/da/texts.php index e1f9114c53..51b4440567 100644 --- a/app/lang/da/texts.php +++ b/app/lang/da/texts.php @@ -512,4 +512,17 @@ return array( 'reset_all' => 'Reset All', 'approve' => 'Approve', + 'token_billing_type_id' => 'Token Billing', + 'token_billing_help' => 'Enables you to store credit cards with your gateway, and charge them at a later date.', + 'token_billing_1' => 'Disabled', + 'token_billing_2' => 'Opt-in - checkbox is shown but not selected', + 'token_billing_3' => 'Opt-out - checkbox is shown and selected', + 'token_billing_4' => 'Always', + 'token_billing_checkbox' => 'Store credit card details', + 'view_in_stripe' => 'View in Stripe', + 'use_card_on_file' => 'Use card on file', + 'edit_payment_details' => 'Edit payment details', + 'token_billing' => 'Save card details', + 'token_billing_secure' => 'All data is stored securely by :stripe_link', + ); diff --git a/app/lang/de/texts.php b/app/lang/de/texts.php index 2adb31ed7f..cc3db81c1b 100644 --- a/app/lang/de/texts.php +++ b/app/lang/de/texts.php @@ -500,6 +500,19 @@ return array( 'payment_email' => 'Zahlungsmail', 'quote_email' => 'Angebotsmail', 'reset_all' => 'Alle zurücksetzen', - 'approve' => 'Approve', + + 'token_billing_type_id' => 'Token Billing', + 'token_billing_help' => 'Enables you to store credit cards with your gateway, and charge them at a later date.', + 'token_billing_1' => 'Disabled', + 'token_billing_2' => 'Opt-in - checkbox is shown but not selected', + 'token_billing_3' => 'Opt-out - checkbox is shown and selected', + 'token_billing_4' => 'Always', + 'token_billing_checkbox' => 'Store credit card details', + 'view_in_stripe' => 'View in Stripe', + 'use_card_on_file' => 'Use card on file', + 'edit_payment_details' => 'Edit payment details', + 'token_billing' => 'Save card details', + 'token_billing_secure' => 'All data is stored securely by :stripe_link', + ); diff --git a/app/lang/en/texts.php b/app/lang/en/texts.php index d01ba177f7..4da38e1dcd 100644 --- a/app/lang/en/texts.php +++ b/app/lang/en/texts.php @@ -510,4 +510,18 @@ return array( 'reset_all' => 'Reset All', 'approve' => 'Approve', + 'token_billing_type_id' => 'Token Billing', + 'token_billing_help' => 'Enables you to store credit cards with your gateway, and charge them at a later date.', + 'token_billing_1' => 'Disabled', + 'token_billing_2' => 'Opt-in - checkbox is shown but not selected', + 'token_billing_3' => 'Opt-out - checkbox is shown and selected', + 'token_billing_4' => 'Always', + 'token_billing_checkbox' => 'Store credit card details', + 'view_in_stripe' => 'View in Stripe', + 'use_card_on_file' => 'Use card on file', + 'edit_payment_details' => 'Edit payment details', + 'token_billing' => 'Save card details', + 'token_billing_secure' => 'All data is stored securely by :stripe_link', + + ); diff --git a/app/lang/es/texts.php b/app/lang/es/texts.php index 80b1dacf65..4d3133ee4c 100644 --- a/app/lang/es/texts.php +++ b/app/lang/es/texts.php @@ -482,4 +482,17 @@ return array( 'reset_all' => 'Reset All', 'approve' => 'Approve', + 'token_billing_type_id' => 'Token Billing', + 'token_billing_help' => 'Enables you to store credit cards with your gateway, and charge them at a later date.', + 'token_billing_1' => 'Disabled', + 'token_billing_2' => 'Opt-in - checkbox is shown but not selected', + 'token_billing_3' => 'Opt-out - checkbox is shown and selected', + 'token_billing_4' => 'Always', + 'token_billing_checkbox' => 'Store credit card details', + 'view_in_stripe' => 'View in Stripe', + 'use_card_on_file' => 'Use card on file', + 'edit_payment_details' => 'Edit payment details', + 'token_billing' => 'Save card details', + 'token_billing_secure' => 'All data is stored securely by :stripe_link', + ); \ No newline at end of file diff --git a/app/lang/fr/texts.php b/app/lang/fr/texts.php index 0e3304f18e..893deff828 100644 --- a/app/lang/fr/texts.php +++ b/app/lang/fr/texts.php @@ -502,5 +502,18 @@ return array( 'quote_email' => 'Quote Email', 'reset_all' => 'Reset All', 'approve' => 'Approve', + + 'token_billing_type_id' => 'Token Billing', + 'token_billing_help' => 'Enables you to store credit cards with your gateway, and charge them at a later date.', + 'token_billing_1' => 'Disabled', + 'token_billing_2' => 'Opt-in - checkbox is shown but not selected', + 'token_billing_3' => 'Opt-out - checkbox is shown and selected', + 'token_billing_4' => 'Always', + 'token_billing_checkbox' => 'Store credit card details', + 'view_in_stripe' => 'View in Stripe', + 'use_card_on_file' => 'Use card on file', + 'edit_payment_details' => 'Edit payment details', + 'token_billing' => 'Save card details', + 'token_billing_secure' => 'All data is stored securely by :stripe_link', ); \ No newline at end of file diff --git a/app/lang/it/texts.php b/app/lang/it/texts.php index 4aae44b0e5..4d69a3d7ea 100644 --- a/app/lang/it/texts.php +++ b/app/lang/it/texts.php @@ -504,5 +504,18 @@ return array( 'quote_email' => 'Quote Email', 'reset_all' => 'Reset All', 'approve' => 'Approve', + + 'token_billing_type_id' => 'Token Billing', + 'token_billing_help' => 'Enables you to store credit cards with your gateway, and charge them at a later date.', + 'token_billing_1' => 'Disabled', + 'token_billing_2' => 'Opt-in - checkbox is shown but not selected', + 'token_billing_3' => 'Opt-out - checkbox is shown and selected', + 'token_billing_4' => 'Always', + 'token_billing_checkbox' => 'Store credit card details', + 'view_in_stripe' => 'View in Stripe', + 'use_card_on_file' => 'Use card on file', + 'edit_payment_details' => 'Edit payment details', + 'token_billing' => 'Save card details', + 'token_billing_secure' => 'All data is stored securely by :stripe_link', ); diff --git a/app/lang/lt/texts.php b/app/lang/lt/texts.php index f171661322..7ae31d36ba 100644 --- a/app/lang/lt/texts.php +++ b/app/lang/lt/texts.php @@ -512,6 +512,19 @@ return array( 'quote_email' => 'Quote Email', 'reset_all' => 'Reset All', 'approve' => 'Approve', + + 'token_billing_type_id' => 'Token Billing', + 'token_billing_help' => 'Enables you to store credit cards with your gateway, and charge them at a later date.', + 'token_billing_1' => 'Disabled', + 'token_billing_2' => 'Opt-in - checkbox is shown but not selected', + 'token_billing_3' => 'Opt-out - checkbox is shown and selected', + 'token_billing_4' => 'Always', + 'token_billing_checkbox' => 'Store credit card details', + 'view_in_stripe' => 'View in Stripe', + 'use_card_on_file' => 'Use card on file', + 'edit_payment_details' => 'Edit payment details', + 'token_billing' => 'Save card details', + 'token_billing_secure' => 'All data is stored securely by :stripe_link', ); diff --git a/app/lang/nb_NO/texts.php b/app/lang/nb_NO/texts.php index 4874c20668..e26530142b 100644 --- a/app/lang/nb_NO/texts.php +++ b/app/lang/nb_NO/texts.php @@ -511,5 +511,18 @@ return array( 'reset_all' => 'Reset All', 'approve' => 'Approve', + 'token_billing_type_id' => 'Token Billing', + 'token_billing_help' => 'Enables you to store credit cards with your gateway, and charge them at a later date.', + 'token_billing_1' => 'Disabled', + 'token_billing_2' => 'Opt-in - checkbox is shown but not selected', + 'token_billing_3' => 'Opt-out - checkbox is shown and selected', + 'token_billing_4' => 'Always', + 'token_billing_checkbox' => 'Store credit card details', + 'view_in_stripe' => 'View in Stripe', + 'use_card_on_file' => 'Use card on file', + 'edit_payment_details' => 'Edit payment details', + 'token_billing' => 'Save card details', + 'token_billing_secure' => 'All data is stored securely by :stripe_link', + ); \ No newline at end of file diff --git a/app/lang/nl/texts.php b/app/lang/nl/texts.php index 1f0dc09221..b9189193a8 100644 --- a/app/lang/nl/texts.php +++ b/app/lang/nl/texts.php @@ -505,6 +505,19 @@ return array( 'quote_email' => 'Quote Email', 'reset_all' => 'Reset All', 'approve' => 'Approve', - + + 'token_billing_type_id' => 'Token Billing', + 'token_billing_help' => 'Enables you to store credit cards with your gateway, and charge them at a later date.', + 'token_billing_1' => 'Disabled', + 'token_billing_2' => 'Opt-in - checkbox is shown but not selected', + 'token_billing_3' => 'Opt-out - checkbox is shown and selected', + 'token_billing_4' => 'Always', + 'token_billing_checkbox' => 'Store credit card details', + 'view_in_stripe' => 'View in Stripe', + 'use_card_on_file' => 'Use card on file', + 'edit_payment_details' => 'Edit payment details', + 'token_billing' => 'Save card details', + 'token_billing_secure' => 'All data is stored securely by :stripe_link', + ); \ No newline at end of file diff --git a/app/lang/pt_BR/texts.php b/app/lang/pt_BR/texts.php index 8cf7074dd1..7ea1062f97 100644 --- a/app/lang/pt_BR/texts.php +++ b/app/lang/pt_BR/texts.php @@ -492,6 +492,19 @@ return array( 'quote_email' => 'Quote Email', 'reset_all' => 'Reset All', 'approve' => 'Approve', + + 'token_billing_type_id' => 'Token Billing', + 'token_billing_help' => 'Enables you to store credit cards with your gateway, and charge them at a later date.', + 'token_billing_1' => 'Disabled', + 'token_billing_2' => 'Opt-in - checkbox is shown but not selected', + 'token_billing_3' => 'Opt-out - checkbox is shown and selected', + 'token_billing_4' => 'Always', + 'token_billing_checkbox' => 'Store credit card details', + 'view_in_stripe' => 'View in Stripe', + 'use_card_on_file' => 'Use card on file', + 'edit_payment_details' => 'Edit payment details', + 'token_billing' => 'Save card details', + 'token_billing_secure' => 'All data is stored securely by :stripe_link', ); diff --git a/app/models/Account.php b/app/models/Account.php index 40ad5e677a..267cb76b9f 100755 --- a/app/models/Account.php +++ b/app/models/Account.php @@ -334,4 +334,15 @@ class Account extends Eloquent return "

" . trans('texts.email_signature') . "
\$account

"; } } + + public function showTokenCheckbox() + { + return $this->token_billing_type_id == TOKEN_BILLING_OPT_IN + || $this->token_billing_type_id == TOKEN_BILLING_OPT_OUT; + } + + public function selectTokenCheckbox() + { + return $this->token_billing_type_id == TOKEN_BILLING_OPT_OUT; + } } diff --git a/app/models/AccountGatewayToken.php b/app/models/AccountGatewayToken.php new file mode 100644 index 0000000000..ae63d6c2d2 --- /dev/null +++ b/app/models/AccountGatewayToken.php @@ -0,0 +1,7 @@ +created_at->format('m/d/y h:i a'); } } + + + public function getGatewayToken() + { + $this->account->load('account_gateways'); + + if (!count($this->account->account_gateways)) { + return false; + } + + $accountGateway = $this->account->account_gateways[0]; + + if ($accountGateway->gateway_id != GATEWAY_STRIPE) { + return false; + } + + $token = AccountGatewayToken::where('client_id', '=', $this->id) + ->where('account_gateway_id', '=', $accountGateway->id)->first(); + + return $token ? $token->token : false; + } + + public function getGatewayLink() + { + $token = $this->getGatewayToken(); + return $token ? "https://dashboard.stripe.com/customers/{$token}" : false; + } } /* diff --git a/app/routes.php b/app/routes.php index 5cba05888d..49ecd9baa1 100755 --- a/app/routes.php +++ b/app/routes.php @@ -318,6 +318,11 @@ define('USER_TYPE_SELF_HOST', 'SELF_HOST'); define('USER_TYPE_CLOUD_HOST', 'CLOUD_HOST'); define('NEW_VERSION_AVAILABLE', 'NEW_VERSION_AVAILABLE'); +define('TOKEN_BILLING_DISABLED', 1); +define('TOKEN_BILLING_OPT_IN', 2); +define('TOKEN_BILLING_OPT_OUT', 3); +define('TOKEN_BILLING_ALWAYS', 4); + /* define('GATEWAY_AMAZON', 30); define('GATEWAY_BLUEPAY', 31); diff --git a/app/views/accounts/payments.blade.php b/app/views/accounts/payments.blade.php index 9fc04806fd..01d91b14ee 100755 --- a/app/views/accounts/payments.blade.php +++ b/app/views/accounts/payments.blade.php @@ -79,14 +79,18 @@ @endforeach - @if($gateway->getHelp()) + @if ($gateway->getHelp())
-
+
{{ $gateway->getHelp() }}
@endif + + @if ($gateway->id == GATEWAY_STRIPE) + {{ Former::select('token_billing_type_id')->options($tokenBillingOptions)->help(trans('texts.token_billing_help')) }} + @endif
@endforeach diff --git a/app/views/clients/show.blade.php b/app/views/clients/show.blade.php index a7605cee8d..2b36611624 100755 --- a/app/views/clients/show.blade.php +++ b/app/views/clients/show.blade.php @@ -10,6 +10,10 @@ {{ Former::text('id')->value($client->public_id) }} + @if ($gatewayLink) + {{ Button::link($gatewayLink, trans('texts.view_in_stripe'), ['target' => '_blank']) }} + @endif + @if ($client->trashed()) {{ Button::primary(trans('texts.restore_client'), ['onclick' => 'onRestoreClick()']) }} @else diff --git a/app/views/invoices/pdf.blade.php b/app/views/invoices/pdf.blade.php index 95ac9b26fc..2c8c01671d 100644 --- a/app/views/invoices/pdf.blade.php +++ b/app/views/invoices/pdf.blade.php @@ -81,7 +81,7 @@ var needsRefresh = false; function refreshPDF() { - PDFJS.disableWorker = true; + PDFJS.workerSrc = '{{ asset('js/pdf_viewer.worker.js') }}'; if ({{ Auth::check() && Auth::user()->force_pdfjs ? 'false' : 'true' }} && (isFirefox || (isChrome && !isChromium))) { var string = getPDFString(); if (!string) return; diff --git a/app/views/invoices/view.blade.php b/app/views/invoices/view.blade.php index 3495217614..b3157ed033 100755 --- a/app/views/invoices/view.blade.php +++ b/app/views/invoices/view.blade.php @@ -30,7 +30,14 @@ @endif @elseif ($invoice->client->account->isGatewayConfigured() && !$invoice->isPaid() && !$invoice->is_recurring) {{ Button::normal(trans('texts.download_pdf'), array('onclick' => 'onDownloadClick()', 'class' => 'btn-lg')) }}   - {{ Button::success_link(URL::to('payment/' . $invitation->invitation_key), trans('texts.pay_now'), array('class' => 'btn-lg')) }} + @if ($hasToken) + {{ DropdownButton::success_lg(trans('texts.pay_now'), [ + ['url' => URL::to("payment/{$invitation->invitation_key}?use_token=true"), 'label' => trans('texts.use_card_on_file')], + ['url' => URL::to('payment/' . $invitation->invitation_key), 'label' => trans('texts.edit_payment_details')] + ])->addClass('btn-lg') }} + @else + {{ Button::success_link(URL::to('payment/' . $invitation->invitation_key), trans('texts.pay_now'), array('class' => 'btn-lg')) }} + @endif @else {{ Button::success('Download PDF', array('onclick' => 'onDownloadClick()', 'class' => 'btn-lg')) }} @endif diff --git a/app/views/payments/payment.blade.php b/app/views/payments/payment.blade.php index 98a04302b6..bee50f514c 100755 --- a/app/views/payments/payment.blade.php +++ b/app/views/payments/payment.blade.php @@ -196,7 +196,15 @@ - @if(isset($acceptedCreditCardTypes)) + @if ($account->showTokenCheckbox()) +
+ selectTokenCheckbox() ? 'CHECKED' : '' }} value="1" style="margin-left:0px; vertical-align:text-top"> + + {{ trans('texts.token_billing_secure', ['stripe_link' => link_to('https://stripe.com/', 'Stripe.com', ['target' => '_blank'])]) }} +
+ @endif + + @if (isset($acceptedCreditCardTypes))
@foreach ($acceptedCreditCardTypes as $card)