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

bug fixes

This commit is contained in:
Hillel Coren 2014-02-02 20:14:56 +02:00
parent 08213f61c3
commit 2d0646ebe2
13 changed files with 319 additions and 152 deletions

View File

@ -430,7 +430,7 @@ class AccountController extends \BaseController {
$account->timezone_id = Input::get('timezone_id') ? Input::get('timezone_id') : null; $account->timezone_id = Input::get('timezone_id') ? Input::get('timezone_id') : null;
$account->date_format_id = Input::get('date_format_id') ? Input::get('date_format_id') : null; $account->date_format_id = Input::get('date_format_id') ? Input::get('date_format_id') : null;
$account->datetime_format_id = Input::get('datetime_format_id') ? Input::get('datetime_format_id') : null; $account->datetime_format_id = Input::get('datetime_format_id') ? Input::get('datetime_format_id') : null;
$account->currency_id = Input::get('currency_id') ? Input::get('currency_id') : null; $account->currency_id = Input::get('currency_id') ? Input::get('currency_id') : 1;
$account->invoice_terms = Input::get('invoice_terms'); $account->invoice_terms = Input::get('invoice_terms');
$account->email_footer = Input::get('email_footer'); $account->email_footer = Input::get('email_footer');

View File

@ -186,7 +186,7 @@ class ClientController extends \BaseController {
$client->private_notes = trim(Input::get('private_notes')); $client->private_notes = trim(Input::get('private_notes'));
$client->size_id = Input::get('size_id') ? Input::get('size_id') : null; $client->size_id = Input::get('size_id') ? Input::get('size_id') : null;
$client->industry_id = Input::get('industry_id') ? Input::get('industry_id') : null; $client->industry_id = Input::get('industry_id') ? Input::get('industry_id') : null;
$client->currency_id = Input::get('currency_id') ? Input::get('currency_id') : null; $client->currency_id = Input::get('currency_id') ? Input::get('currency_id') : 1;
$client->payment_terms = Input::get('payment_terms'); $client->payment_terms = Input::get('payment_terms');
$client->website = trim(Input::get('website')); $client->website = trim(Input::get('website'));

View File

@ -148,146 +148,6 @@ class InvoiceController extends \BaseController {
return View::make('invoices.view', $data); return View::make('invoices.view', $data);
} }
private function createGateway($accountGateway)
{
$gateway = Omnipay::create($accountGateway->gateway->provider);
$config = json_decode($accountGateway->config);
/*
$gateway->setSolutionType ("Sole");
$gateway->setLandingPage("Billing");
*/
foreach ($config as $key => $val)
{
if (!$val)
{
continue;
}
$function = "set" . ucfirst($key);
$gateway->$function($val);
}
return $gateway;
}
private function getPaymentDetails($invoice)
{
$data = array(
'firstName' => '',
'lastName' => '',
);
$card = new CreditCard($data);
return [
'amount' => $invoice->amount,
'card' => $card,
'currency' => 'USD',
'returnUrl' => URL::to('complete'),
'cancelUrl' => URL::to('/'),
];
}
public function show_payment($invitationKey)
{
$invitation = Invitation::with('invoice.invoice_items', 'invoice.client.account.account_gateways.gateway')->where('invitation_key', '=', $invitationKey)->firstOrFail();
$invoice = $invitation->invoice;
$accountGateway = $invoice->client->account->account_gateways[0];
$gateway = InvoiceController::createGateway($accountGateway);
try
{
$details = InvoiceController::getPaymentDetails($invoice);
$response = $gateway->purchase($details)->send();
$ref = $response->getTransactionReference();
if (!$ref)
{
return Utils::fatalError('Sorry, there was an error processing your payment. Please try again later.<p>', $response->getMessage());
}
$payment = Payment::createNew();
$payment->invitation_id = $invitation->id;
$payment->account_gateway_id = $accountGateway->id;
$payment->invoice_id = $invoice->id;
$payment->amount = $invoice->amount;
$payment->client_id = $invoice->client_id;
$payment->contact_id = $invitation->contact_id;
$payment->transaction_reference = $ref;
$payment->payment_date = date_create();
$payment->save();
if ($response->isSuccessful())
{
}
else if ($response->isRedirect())
{
$response->redirect();
}
else
{
return Utils::fatalError('Sorry, there was an error processing your payment. Please try again later.<p>');
}
}
catch (\Exception $e)
{
return Utils::fatalError('Sorry, there was an error processing your payment. Please try again later.<p>', $e);
}
}
public function do_payment()
{
$payerId = Request::query('PayerID');
$token = Request::query('token');
$payment = Payment::with('invitation', 'invoice.invoice_items')->where('transaction_reference','=',$token)->firstOrFail();
$invoice = Invoice::with('client.account.account_gateways.gateway')->where('id', '=', $payment->invoice_id)->firstOrFail();
$accountGateway = $invoice->client->account->account_gateways[0];
$gateway = InvoiceController::createGateway($accountGateway);
try
{
$details = InvoiceController::getPaymentDetails($payment->invoice);
$response = $gateway->completePurchase($details)->send();
$ref = $response->getTransactionReference();
if ($response->isSuccessful())
{
$payment->payer_id = $payerId;
$payment->transaction_reference = $ref;
$payment->save();
if ($payment->amount >= $invoice->amount)
{
$invoice->invoice_status_id = INVOICE_STATUS_PAID;
}
else
{
$invoice->invoice_status_id = INVOICE_STATUS_PARTIAL;
}
$invoice->save();
Event::fire('invoice.paid', $payment);
Session::flash('message', 'Successfully applied payment');
return Redirect::to('view/' . $payment->invitation->invitation_key);
}
else
{
return Utils::fatalError('Sorry, there was an error processing your payment. Please try again later.<p>', $response->getMessage());
}
}
catch (\Exception $e)
{
return Utils::fatalError('Sorry, there was an error processing your payment. Please try again later.<p>', $e);
}
}
public function edit($publicId) public function edit($publicId)
{ {
$invoice = Invoice::scope($publicId)->with('account.country', 'client.contacts', 'client.country', 'invoice_items')->firstOrFail(); $invoice = Invoice::scope($publicId)->with('account.country', 'client.contacts', 'client.country', 'invoice_items')->firstOrFail();

View File

@ -95,6 +95,228 @@ class PaymentController extends \BaseController
return View::make('payments.edit', $data); return View::make('payments.edit', $data);
} }
private function createGateway($accountGateway)
{
$gateway = Omnipay::create($accountGateway->gateway->provider);
$config = json_decode($accountGateway->config);
/*
$gateway->setSolutionType ("Sole");
$gateway->setLandingPage("Billing");
*/
foreach ($config as $key => $val)
{
if (!$val)
{
continue;
}
$function = "set" . ucfirst($key);
$gateway->$function($val);
}
return $gateway;
}
private function getPaymentDetails($invoice, $input = null)
{
if ($input)
{
$data = [
'firstName' => $input['first_name'],
'lastName' => $input['last_name'],
'number' => $input['card_number'],
'expiryMonth' => $input['expiration_month'],
'expiryYear' => $input['expiration_year'],
'cvv' => $input['cvv'],
'billingAddress1' => $input['address1'],
'billingAddress2' => $input['address2'],
'billingCity' => $input['city'],
'billingState' => $input['state'],
'billingPostcode' => $input['postal_code'],
'shippingAddress1' => $input['address1'],
'shippingAddress2' => $input['address2'],
'shippingCity' => $input['city'],
'shippingState' => $input['state'],
'shippingPostcode' => $input['postal_code'],
];
Session::put($invoice->invoice_number . '_details', $data);
}
else
{
$data = Session::get($invoice->invoice_number . '_details');
}
$card = new CreditCard($data);
return [
'amount' => $invoice->amount,
'card' => $card,
'currency' => $invoice->client->currency->code,
'returnUrl' => URL::to('complete'),
'cancelUrl' => URL::to('/'),
];
}
public function show_payment($invitationKey)
{
$invitation = Invitation::with('contact', 'invoice.client')->where('invitation_key', '=', $invitationKey)->firstOrFail();
$invoice = $invitation->invoice;
$client = $invoice->client;
$data = [
'invitationKey' => $invitationKey,
'invoice' => $invoice,
'client' => $client,
'contact' => $invitation->contact
];
return View::make('payments.payment', $data);
}
public function do_payment($invitationKey)
{
$rules = array(
'first_name' => 'required',
'last_name' => 'required',
'card_number' => 'required',
'expiration_month' => 'required',
'expiration_year' => 'required',
'cvv' => 'required',
'address1' => 'required',
'city' => 'required',
'state' => 'required',
'postal_code' => 'required',
);
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails())
{
return Redirect::to('payment/' . $invitationKey)
->withErrors($validator);
}
else
{
$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];
$gateway = self::createGateway($accountGateway);
try
{
$details = self::getPaymentDetails($invoice, Input::all());
$response = $gateway->purchase($details)->send();
$ref = $response->getTransactionReference();
if (!$ref)
{
Session::flash('error', $response->getMessage());
return Redirect::to('payment/' . $invitationKey)
->withInput();
}
if ($response->isSuccessful())
{
self::createPayment($invitation, $ref);
$invoice->invoice_status_id = INVOICE_STATUS_PAID;
$invoice->save();
Event::fire('invoice.paid', $payment);
Session::flash('message', 'Successfully applied payment');
return Redirect::to('view/' . $payment->invitation->invitation_key);
}
else if ($response->isRedirect())
{
$invitation->transaction_reference = $ref;
$invitation->save();
$response->redirect();
}
else
{
return Utils::fatalError('Sorry, there was an error processing your payment. Please try again later.<p>');
}
}
catch (\Exception $e)
{
Session::flash('error', $e->getMessage());
return Redirect::to('payment/' . $invitationKey)
->withInput();
}
}
}
private function createPayment($invitation, $ref, $payerId = null)
{
$invoice = $invitation->invoice;
$accountGateway = $invoice->client->account->account_gateways[0];
$payment = Payment::createNew();
$payment->invitation_id = $invitation->id;
$payment->account_gateway_id = $accountGateway->id;
$payment->invoice_id = $invoice->id;
$payment->amount = $invoice->amount;
$payment->client_id = $invoice->client_id;
$payment->contact_id = $invitation->contact_id;
$payment->transaction_reference = $ref;
$payment->payment_date = date_create()->format('Y-m-d');
if ($payerId)
{
$payment->payer_id = $payerId;
}
$payment->save();
return $payment;
}
public function offsite_payment()
{
$payerId = Request::query('PayerID');
$token = Request::query('token');
$invitation = Invitation::with('invoice.client.currency', 'invoice.client.account.account_gateways.gateway')->where('transaction_reference', '=', $token)->firstOrFail();
$invoice = $invitation->invoice;
$accountGateway = $invoice->client->account->account_gateways[0];
$gateway = self::createGateway($accountGateway);
try
{
$details = self::getPaymentDetails($invoice);
$response = $gateway->completePurchase($details)->send();
$ref = $response->getTransactionReference();
if ($response->isSuccessful())
{
$payment = self::createPayment($invitation, $ref, $payerId);
$invoice->invoice_status_id = INVOICE_STATUS_PAID;
$invoice->save();
Event::fire('invoice.paid', $payment);
Session::flash('message', 'Successfully applied payment');
return Redirect::to('view/' . $invitation->invitation_key);
}
else
{
return Utils::fatalError('Sorry, there was an error processing your payment. Please try again later.<p>', $response->getMessage());
}
}
catch (\Exception $e)
{
return Utils::fatalError('Sorry, there was an error processing your payment. Please try again later.<p>', $e);
}
}
public function store() public function store()
{ {
return $this->save(); return $this->save();

View File

@ -106,6 +106,7 @@ class ConfideSetupUsersTable extends Migration {
$t->string('precision'); $t->string('precision');
$t->string('thousand_separator'); $t->string('thousand_separator');
$t->string('decimal_separator'); $t->string('decimal_separator');
$t->string('code');
}); });
Schema::create('sizes', function($t) Schema::create('sizes', function($t)
@ -230,7 +231,7 @@ class ConfideSetupUsersTable extends Migration {
$t->increments('id'); $t->increments('id');
$t->unsignedInteger('user_id'); $t->unsignedInteger('user_id');
$t->unsignedInteger('account_id')->index(); $t->unsignedInteger('account_id')->index();
$t->unsignedInteger('currency_id')->default(1)->nullable(); $t->unsignedInteger('currency_id')->default(1);
$t->timestamps(); $t->timestamps();
$t->softDeletes(); $t->softDeletes();
@ -353,6 +354,7 @@ class ConfideSetupUsersTable extends Migration {
$t->timestamps(); $t->timestamps();
$t->softDeletes(); $t->softDeletes();
$t->string('transaction_reference');
$t->timestamp('sent_date'); $t->timestamp('sent_date');
$t->timestamp('viewed_date'); $t->timestamp('viewed_date');

View File

@ -118,9 +118,9 @@ class ConstantsSeeder extends Seeder
PaymentTerm::create(array('num_days' => 30, 'name' => 'Net 30')); PaymentTerm::create(array('num_days' => 30, 'name' => 'Net 30'));
PaymentTerm::create(array('num_days' => 60, 'name' => 'Net 60')); PaymentTerm::create(array('num_days' => 60, 'name' => 'Net 60'));
Currency::create(array('name' => 'US Dollar', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.')); Currency::create(array('name' => 'US Dollar', 'code' => 'USD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'));
Currency::create(array('name' => 'Pound Sterling', 'symbol' => '£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.')); Currency::create(array('name' => 'Pound Sterling', 'code' => 'GBP', 'symbol' => '£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'));
Currency::create(array('name' => 'Euro', 'symbol' => '€', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.')); Currency::create(array('name' => 'Euro', 'code' => 'EUR', 'symbol' => '€', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'));
DatetimeFormat::create(array('format' => 'd/M/Y g:i a', 'label' => '10/Mar/2013')); DatetimeFormat::create(array('format' => 'd/M/Y g:i a', 'label' => '10/Mar/2013'));

View File

@ -37,6 +37,11 @@ class Client extends EntityModel
return $this->belongsTo('Country'); return $this->belongsTo('Country');
} }
public function currency()
{
return $this->belongsTo('Currency');
}
public function size() public function size()
{ {
return $this->belongsTo('Size'); return $this->belongsTo('Size');

View File

@ -53,7 +53,7 @@ class ClientRepository
$client->private_notes = trim($data['private_notes']); $client->private_notes = trim($data['private_notes']);
$client->size_id = $data['size_id'] ? $data['size_id'] : null; $client->size_id = $data['size_id'] ? $data['size_id'] : null;
$client->industry_id = $data['industry_id'] ? $data['industry_id'] : null; $client->industry_id = $data['industry_id'] ? $data['industry_id'] : null;
$client->currency_id = $data['currency_id'] ? $data['currency_id'] : null; $client->currency_id = $data['currency_id'] ? $data['currency_id'] : 1;
$client->payment_terms = $data['payment_terms']; $client->payment_terms = $data['payment_terms'];
$client->website = trim($data['website']); $client->website = trim($data['website']);
$client->save(); $client->save();

View File

@ -64,9 +64,10 @@ Route::get('/rocksteady', 'HomeController@showWelcome');
Route::get('log_error', 'HomeController@logError'); Route::get('log_error', 'HomeController@logError');
Route::post('get_started', 'AccountController@getStarted'); Route::post('get_started', 'AccountController@getStarted');
Route::get('view/{invoice_key}', 'InvoiceController@view'); Route::get('view/{invitation_key}', 'InvoiceController@view');
Route::get('payment/{invoice_key}', 'InvoiceController@show_payment'); Route::get('payment/{invitation_key}', 'PaymentController@show_payment');
Route::get('complete', 'InvoiceController@do_payment'); Route::post('payment/{invitation_key}', 'PaymentController@do_payment');
Route::get('complete', 'PaymentController@offsite_payment');
Route::post('signup/validate', 'AccountController@checkEmail'); Route::post('signup/validate', 'AccountController@checkEmail');
Route::post('signup/submit', 'AccountController@submitSignup'); Route::post('signup/submit', 'AccountController@submitSignup');

View File

@ -70,7 +70,7 @@
<span class="icon-bar"></span> <span class="icon-bar"></span>
<span class="icon-bar"></span> <span class="icon-bar"></span>
</button> </button>
<a href="{{ URL::to('/rocksteady') }}" class='navbar-brand'>Invoice Ninja <sup><small>BETA</small></sup></a> <a href="{{ URL::to('/rocksteady') }}" class='navbar-brand'>Invoice Ninja</a>
</div> </div>
<div class="collapse navbar-collapse" id="navbar-collapse-1"> <div class="collapse navbar-collapse" id="navbar-collapse-1">

View File

@ -0,0 +1,77 @@
@extends('header')
@section('content')
<style type="text/css">
div > label.control-label
{
font-weight: normal !important;
}d
</style>
{{ Former::open('payment/' . $invitationKey)->rules(array(
'first_name' => 'required',
'last_name' => 'required',
'card_number' => 'required',
'expiration_month' => 'required',
'expiration_year' => 'required',
'cvv' => 'required',
'address1' => 'required',
'city' => 'required',
'state' => 'required',
'postal_code' => 'required'
)) }}
{{ Former::populate($client) }}
{{ Former::populateField('first_name', $contact->first_name) }}
{{ Former::populateField('last_name', $contact->last_name) }}
<div class="row">
<div class="col-md-6 col-md-offset-2">
{{ Former::legend('Secure Payment') }}
{{ Former::text('first_name') }}
{{ Former::text('last_name') }}
<p>&nbsp;<p/>
{{ Former::text('card_number') }}
{{ Former::select('expiration_month')->addOption('','')
->addOption('01 - January', '1')
->addOption('02 - February', '2')
->addOption('03 - March', '3')
->addOption('04 - April', '4')
->addOption('05 - May', '5')
->addOption('06 - June', '6')
->addOption('07 - July', '7')
->addOption('08 - August', '8')
->addOption('09 - September', '9')
->addOption('10 - October', '10')
->addOption('11 - November', '11')
->addOption('12 - December', '12')
}}
{{ Former::select('expiration_year')->addOption('','')
->addOption('2014', '2014')
->addOption('2015', '2015')
->addOption('2016', '2016')
->addOption('2017', '2017')
->addOption('2018', '2018')
->addOption('2019', '2019')
->addOption('2020', '2020')
}}
{{ Former::text('cvv')->label('CVV') }}
<p>&nbsp;<p/>
{{ Former::text('address1')->label('Street') }}
{{ Former::text('address2')->label('Apt/Suite') }}
{{ Former::text('city') }}
{{ Former::text('state')->label('State/Province') }}
{{ Former::text('postal_code') }}
{{ Former::actions( Button::primary_submit_lg('Pay Now - ' . Utils::formatMoney($invoice->amount, $client->currency_id) )) }}
</div>
</div>
{{ Former::close() }}
@stop

View File

@ -7,7 +7,7 @@ div.required > label {
} }
label.checkbox, label.checkbox,
label.control-label { div > label.control-label {
font-weight: normal !important; font-weight: normal !important;
} }