1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-10 05:02:36 +01:00

Trial Flow:

This commit is contained in:
David Bomba 2022-02-23 17:39:36 +11:00
parent 242accde6f
commit bba3c79553
4 changed files with 147 additions and 11 deletions

View File

@ -12,6 +12,7 @@
namespace App\Http\Controllers\ClientPortal;
use App\Factory\RecurringInvoiceFactory;
use App\Http\Controllers\Controller;
use App\Http\Requests\ClientPortal\Uploads\StoreUploadRequest;
use App\Libraries\MultiDB;
@ -19,9 +20,11 @@ use App\Models\Account;
use App\Models\ClientContact;
use App\Models\Company;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use App\Models\Invoice;
use App\Models\RecurringInvoice;
use App\Models\Subscription;
use App\Repositories\SubscriptionRepository;
use App\Utils\Ninja;
use App\Utils\Traits\MakesHash;
use Illuminate\Contracts\Routing\ResponseFactory;
@ -76,10 +79,14 @@ class NinjaPlanController extends Controller
$data['gateway'] = $gateway;
$gateway_driver = $gateway->driver()->init();
$gateway_driver = $gateway->driver(auth()->guard('contact')->user()->client)->init();
$customer = $gateway_driver->findOrCreateCustomer();
$setupIntent = \Stripe\SetupIntent::create([
'payment_method_types' => ['card'],
'usage' => 'off_session',
'customer' => $customer->id
]);
$data['intent'] = $setupIntent;
@ -91,6 +98,82 @@ class NinjaPlanController extends Controller
}
public function trial_confirmation(Request $request)
{
$client = auth()->guard('contact')->user()->client;
$client->fill($request->all());
$client->save();
//store payment method
$gateway = CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->first();
$gateway_driver = $gateway->driver(auth()->guard('contact')->user()->client)->init();
$stripe_response = json_decode($request->input('gateway_response'));
$customer = $gateway_driver->findOrCreateCustomer();
$gateway_driver->attach($stripe_response->payment_method, $customer);
$method = $gateway_driver->getStripePaymentMethod($stripe_response->payment_method);
$this->storePaymentMethod($method, $request->payment_method_id, $customer);
$payment_meta = new \stdClass;
$payment_meta->exp_month = (string) $method->card->exp_month;
$payment_meta->exp_year = (string) $method->card->exp_year;
$payment_meta->brand = (string) $method->card->brand;
$payment_meta->last4 = (string) $method->card->last4;
$payment_meta->type = GatewayType::CREDIT_CARD;
$data = [
'payment_meta' => $payment_meta,
'token' => $method->id,
'payment_method_id' => GatewayType::CREDIT_CARD,
];
$gateway_driver->storeGatewayToken($data, ['gateway_customer_reference' => $customer->id]);
//set free trial
$account = auth()->guard('contact')->user()->company->account;
$account->trial_started = now();
$account->trial_plan = 'pro';
$account->save();
//create recurring invoice
$subscription_repo = new SubscriptionRepository();
$subscription = Subscription::find(6);
$recurring_invoice = RecurringInvoiceFactory::create($subscription->company_id, $subscription->user_id);
$recurring_invoice->client_id = $client->id;
$recurring_invoice->line_items = $subscription_repo->generateLineItems($subscription, true, false);
$recurring_invoice->subscription_id = $subscription->id;
$recurring_invoice->frequency_id = $subscription->frequency_id ?: RecurringInvoice::FREQUENCY_MONTHLY;
$recurring_invoice->date = now()->addDays(14);
$recurring_invoice->remaining_cycles = -1;
$recurring_invoice->auto_bill = $client->getSetting('auto_bill');
$recurring_invoice->auto_bill_enabled = $this->setAutoBillFlag($recurring_invoice->auto_bill);
$recurring_invoice->due_date_days = 'terms';
$recurring_invoice->next_send_date = now()->addDays(14)->format('Y-m-d');
$recurring_invoice->next_send_date = $recurring_invoice->nextSendDate();
$recurring_invoice->save();
$recurring_invoice->service()->start();
return redirect('/');
}
private function setAutoBillFlag($auto_bill)
{
if ($auto_bill == 'always' || $auto_bill == 'optout') {
return true;
}
return false;
}
public function plan()
{
return $this->trial();

View File

@ -84,8 +84,8 @@ class CreateAccount
{
$sp794f3f->hosted_client_count = config('ninja.quotas.free.clients');
$sp794f3f->hosted_company_count = config('ninja.quotas.free.max_companies');
$sp794f3f->trial_started = now();
$sp794f3f->trial_plan = 'pro';
// $sp794f3f->trial_started = now();
// $sp794f3f->trial_plan = 'pro';
}

View File

@ -33,7 +33,11 @@
</div>
<div class="w-1/2 overflow-hidden">
<form>
<form id="card-form" action="{{ route('client.trial.response') }}" method="post">
@csrf
<input type="hidden" name="gateway_response">
<div class="alert alert-failure mb-4" hidden id="errors"></div>
<div class="form-group mb-2">
<input type="text" class="form-control block
w-full
@ -48,7 +52,7 @@
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none" id="address1"
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none" id="name"
placeholder="{{ ctrans('texts.name') }}"
name="name"
value="{{$client->present()->name()}}">
@ -68,7 +72,7 @@
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none" id="exampleInput91"
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none" id="address1"
placeholder="{{ ctrans('texts.address1') }}"
name="address1"
value="{{$client->address1}}">
@ -163,9 +167,9 @@
</div>
<div class="form-group mb-2">
<select name="countries" id="country" class="form-select w-full py-2 text-gray-700">
<select name="country" id="country" class="form-select w-full py-2 text-gray-700">
@foreach($countries as $country)
<option value="{{ $client->country->iso_3166_2 }}">{{ $client->country->iso_3166_2 }} ({{ $client->country->name }})</option>
<option value="{{ $client->country->id }}">{{ $client->country->iso_3166_2 }} ({{ $client->country->name }})</option>
@endforeach
</select>
</div>
@ -213,21 +217,69 @@
<script type="text/javascript">
var stripe = Stripe('{{ $gateway->getPublishableKey()}}');
var client_secret = '{{ $intent->client_secret }}';
var elements = stripe.elements({
clientSecret: '{{ $intent->client_secret }}',
clientSecret: client_secret,
});
var cardElement = elements.create('card', {
value: {
postalCode: document.querySelector('meta[name=client-postal-code]').content,
name: document.querySelector('meta[name=client-name').content
postalCode: document.querySelector('input[name=postal_code]').content,
name: document.querySelector('input[name=name]').content
}
});
cardElement.mount('#card-element');
const form = document.getElementById('card-form');
var e = document.getElementById("country");
var country_value = e.options[e.selectedIndex].value;
document
.getElementById('pay-now')
.addEventListener('click', () => {
let payNowButton = document.getElementById('pay-now');
payNowButton = payNowButton;
payNowButton.disabled = true;
payNowButton.querySelector('svg').classList.remove('hidden');
payNowButton.querySelector('span').classList.add('hidden');
stripe.handleCardSetup(this.client_secret, cardElement, {
payment_method_data: {
billing_details: {
name: document.querySelector('input[name=name]').content,
},
}
})
.then((result) => {
if (result.error) {
let errors = document.getElementById('errors');
let payNowButton = document.getElementById('pay-now');
errors.textContent = '';
errors.textContent = result.error.message;
errors.hidden = false;
payNowButton.disabled = false;
payNowButton.querySelector('svg').classList.add('hidden');
payNowButton.querySelector('span').classList.remove('hidden');
return;
}
document.querySelector(
'input[name="gateway_response"]'
).value = JSON.stringify(result.setupIntent);
document.getElementById('card-form').submit();
});
});
</script>
@endpush

View File

@ -28,6 +28,7 @@ Route::get('documents/{document_hash}', 'ClientPortal\DocumentController@publicD
Route::get('error', 'ClientPortal\ContactHashLoginController@errorPage')->name('client.error');
Route::get('client/payment/{contact_key}/{payment_id}', 'ClientPortal\InvitationController@paymentRouter')->middleware(['domain_db','contact_key_login']);
Route::get('client/ninja/{contact_key}/{company_key}', 'ClientPortal\NinjaPlanController@index')->name('client.ninja_contact_login')->middleware(['domain_db']);
Route::post('client/ninja/trial_confirmation', 'ClientPortal\NinjaPlanController@trial_confirmation')->name('client.trial.response')->middleware(['domain_db']);
Route::group(['middleware' => ['auth:contact', 'locale', 'domain_db','check_client_existence'], 'prefix' => 'client', 'as' => 'client.'], function () {
Route::get('dashboard', 'ClientPortal\DashboardController@index')->name('dashboard'); // name = (dashboard. index / create / show / update / destroy / edit