This commit is contained in:
David Bomba 2021-06-22 21:45:42 +10:00
commit 62cd32785a
97 changed files with 162955 additions and 159952 deletions

View File

@ -49,37 +49,16 @@ jobs:
sudo rm -rf bootstrap/cache/* sudo rm -rf bootstrap/cache/*
sudo rm -rf node_modules sudo rm -rf node_modules
sudo rm -rf .git sudo rm -rf .git
# - name: Prune Git History
# run: | - name: Build project
# sudo git gc
# sudo git gc --aggressive
# sudo git prune
- name: Build project # This would actually build your project, using zip for an example artifact
run: | run: |
zip -r ./invoiceninja.zip .* -x "../*" zip -r ./invoiceninja.zip .* -x "../*"
- name: Get tag name - name: Release
id: get_tag_name uses: softprops/action-gh-release@v1
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}-release if: startsWith(github.ref, 'refs/tags/')
- name: Create Release
id: create_release
uses: actions/create-release@v1
env: env:
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
tag_name: ${{ steps.get_tag_name.outputs.VERSION }} files: |
release_name: Release ${{ steps.get_tag_name.outputs.VERSION }} invoiceninja.zip
draft: false
prerelease: false
- name: Upload Release Asset
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{secrets.RELEASE_TOKEN}}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
asset_path: ./invoiceninja.zip
asset_name: invoiceninja.zip
asset_content_type: application/zip

View File

@ -1 +1 @@
5.2.5 5.2.6

View File

@ -67,7 +67,7 @@ class CheckData extends Command
/** /**
* @var string * @var string
*/ */
protected $signature = 'ninja:check-data {--database=} {--fix=} {--client_id=}'; protected $signature = 'ninja:check-data {--database=} {--fix=} {--client_id=} {--paid_to_date=}';
/** /**
* @var string * @var string
@ -78,6 +78,10 @@ class CheckData extends Command
protected $isValid = true; protected $isValid = true;
protected $wrong_paid_to_dates = 0;
protected $wrong_balances = 0;
public function handle() public function handle()
{ {
$database_connection = $this->option('database') ? $this->option('database') : 'Connected to Default DB'; $database_connection = $this->option('database') ? $this->option('database') : 'Connected to Default DB';
@ -305,10 +309,10 @@ class CheckData extends Command
private function checkPaidToDates() private function checkPaidToDates()
{ {
$wrong_paid_to_dates = 0; $this->wrong_paid_to_dates = 0;
$credit_total_applied = 0; $credit_total_applied = 0;
Client::withTrashed()->where('is_deleted', 0)->cursor()->each(function ($client) use ($wrong_paid_to_dates, $credit_total_applied) { Client::withTrashed()->where('is_deleted', 0)->cursor()->each(function ($client) use ($credit_total_applied) {
$total_invoice_payments = 0; $total_invoice_payments = 0;
foreach ($client->invoices()->where('is_deleted', false)->where('status_id', '>', 1)->get() as $invoice) { foreach ($client->invoices()->where('is_deleted', false)->where('status_id', '>', 1)->get() as $invoice) {
@ -330,25 +334,30 @@ class CheckData extends Command
if (round($total_invoice_payments, 2) != round($client->paid_to_date, 2)) { if (round($total_invoice_payments, 2) != round($client->paid_to_date, 2)) {
$wrong_paid_to_dates++; $this->wrong_paid_to_dates++;
$this->logMessage($client->present()->name.' id = # '.$client->id." - Paid to date does not match Client Paid To Date = {$client->paid_to_date} - Invoice Payments = {$total_invoice_payments}"); $this->logMessage($client->present()->name.' id = # '.$client->id." - Paid to date does not match Client Paid To Date = {$client->paid_to_date} - Invoice Payments = {$total_invoice_payments}");
$this->isValid = false; $this->isValid = false;
if($this->option('paid_to_date')){
$this->logMessage("# {$client->id} " . $client->present()->name.' - '.$client->number." Fixing {$client->paid_to_date} to {$total_invoice_payments}");
$client->paid_to_date = $total_invoice_payments;
$client->save();
}
} }
}); });
$this->logMessage("{$wrong_paid_to_dates} clients with incorrect paid to dates"); $this->logMessage("{$this->wrong_paid_to_dates} clients with incorrect paid to dates");
} }
private function checkInvoicePayments() private function checkInvoicePayments()
{ {
$wrong_balances = 0; $this->wrong_balances = 0;
$wrong_paid_to_dates = 0;
Client::cursor()->where('is_deleted', 0)->each(function ($client) use ($wrong_balances) { Client::cursor()->where('is_deleted', 0)->each(function ($client) {
$client->invoices->where('is_deleted', false)->whereIn('status_id', '!=', Invoice::STATUS_DRAFT)->each(function ($invoice) use ($wrong_balances, $client) { $client->invoices->where('is_deleted', false)->whereIn('status_id', '!=', Invoice::STATUS_DRAFT)->each(function ($invoice) use ($client) {
$total_amount = $invoice->payments()->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment:: STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED])->get()->sum('pivot.amount'); $total_amount = $invoice->payments()->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment:: STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED])->get()->sum('pivot.amount');
$total_refund = $invoice->payments()->get()->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment:: STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED])->sum('pivot.refunded'); $total_refund = $invoice->payments()->get()->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment:: STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED])->sum('pivot.refunded');
$total_credit = $invoice->credits()->get()->sum('amount'); $total_credit = $invoice->credits()->get()->sum('amount');
@ -357,7 +366,7 @@ class CheckData extends Command
$calculated_paid_amount = $invoice->amount - $invoice->balance - $total_credit; $calculated_paid_amount = $invoice->amount - $invoice->balance - $total_credit;
if ((string)$total_paid != (string)($invoice->amount - $invoice->balance - $total_credit)) { if ((string)$total_paid != (string)($invoice->amount - $invoice->balance - $total_credit)) {
$wrong_balances++; $this->wrong_balances++;
$this->logMessage($client->present()->name.' - '.$client->id." - Total Amount = {$total_amount} != Calculated Total = {$calculated_paid_amount} - Total Refund = {$total_refund} Total credit = {$total_credit}"); $this->logMessage($client->present()->name.' - '.$client->id." - Total Amount = {$total_amount} != Calculated Total = {$calculated_paid_amount} - Total Refund = {$total_refund} Total credit = {$total_credit}");
@ -367,13 +376,13 @@ class CheckData extends Command
}); });
$this->logMessage("{$wrong_balances} clients with incorrect invoice balances"); $this->logMessage("{$this->wrong_balances} clients with incorrect invoice balances");
} }
private function checkClientBalances() private function checkClientBalances()
{ {
$wrong_balances = 0; $this->wrong_balances = 0;
$wrong_paid_to_dates = 0; $this->wrong_paid_to_dates = 0;
foreach (Client::cursor()->where('is_deleted', 0) as $client) { foreach (Client::cursor()->where('is_deleted', 0) as $client) {
//$invoice_balance = $client->invoices->where('is_deleted', false)->where('status_id', '>', 1)->sum('balance'); //$invoice_balance = $client->invoices->where('is_deleted', false)->where('status_id', '>', 1)->sum('balance');
@ -387,14 +396,14 @@ class CheckData extends Command
$ledger = CompanyLedger::where('client_id', $client->id)->orderBy('id', 'DESC')->first(); $ledger = CompanyLedger::where('client_id', $client->id)->orderBy('id', 'DESC')->first();
if ($ledger && (string) $invoice_balance != (string) $client->balance) { if ($ledger && (string) $invoice_balance != (string) $client->balance) {
$wrong_paid_to_dates++; $this->wrong_paid_to_dates++;
$this->logMessage($client->present()->name.' - '.$client->id." - calculated client balances do not match Invoice Balances = {$invoice_balance} - Client Balance = ".rtrim($client->balance, '0'). " Ledger balance = {$ledger->balance}"); $this->logMessage($client->present()->name.' - '.$client->id." - calculated client balances do not match Invoice Balances = {$invoice_balance} - Client Balance = ".rtrim($client->balance, '0'). " Ledger balance = {$ledger->balance}");
$this->isValid = false; $this->isValid = false;
} }
} }
$this->logMessage("{$wrong_paid_to_dates} clients with incorrect client balances"); $this->logMessage("{$this->wrong_paid_to_dates} clients with incorrect client balances");
} }
//fix for client balances = //fix for client balances =
@ -406,8 +415,8 @@ class CheckData extends Command
private function checkInvoiceBalances() private function checkInvoiceBalances()
{ {
$wrong_balances = 0; $this->wrong_balances = 0;
$wrong_paid_to_dates = 0; $this->wrong_paid_to_dates = 0;
foreach (Client::where('is_deleted', 0)->cursor() as $client) { foreach (Client::where('is_deleted', 0)->cursor() as $client) {
$invoice_balance = $client->invoices()->where('is_deleted', false)->where('status_id', '>', 1)->get()->sum('balance'); $invoice_balance = $client->invoices()->where('is_deleted', false)->where('status_id', '>', 1)->get()->sum('balance');
@ -419,14 +428,14 @@ class CheckData extends Command
$ledger = CompanyLedger::where('client_id', $client->id)->orderBy('id', 'DESC')->first(); $ledger = CompanyLedger::where('client_id', $client->id)->orderBy('id', 'DESC')->first();
if ($ledger && number_format($invoice_balance, 4) != number_format($client->balance, 4)) { if ($ledger && number_format($invoice_balance, 4) != number_format($client->balance, 4)) {
$wrong_balances++; $this->wrong_balances++;
$this->logMessage("# {$client->id} " . $client->present()->name.' - '.$client->number." - Balance Failure - Invoice Balances = {$invoice_balance} Client Balance = {$client->balance} Ledger Balance = {$ledger->balance}"); $this->logMessage("# {$client->id} " . $client->present()->name.' - '.$client->number." - Balance Failure - Invoice Balances = {$invoice_balance} Client Balance = {$client->balance} Ledger Balance = {$ledger->balance}");
$this->isValid = false; $this->isValid = false;
} }
} }
$this->logMessage("{$wrong_balances} clients with incorrect balances"); $this->logMessage("{$this->wrong_balances} clients with incorrect balances");
} }
private function checkLogoFiles() private function checkLogoFiles()

View File

@ -0,0 +1,95 @@
<?php
namespace App\Console\Commands;
use App\Libraries\MultiDB;
use App\Models\Company;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
class SubdomainFill extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'ninja:subdomain';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Pad subdomains';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$c1 = Company::on('db-ninja-01')->whereNull('subdomain')->orWhere('subdomain', '')->get();
$c2 = Company::on('db-ninja-02')->whereNull('subdomain')->orWhere('subdomain', '')->get();
$c1->each(function ($company){
$company->subdomain = MultiDB::randomSubdomainGenerator();
$company->save();
});
$c2->each(function ($company){
$company->subdomain = MultiDB::randomSubdomainGenerator();
$company->save();
});
$db1 = Company::on('db-ninja-01')->get();
$db1->each(function ($company){
$db2 = Company::on('db-ninja-02a')->find($company->id);
if($db2)
{
$db2->subdomain = $company->subdomain;
$db2->save();
}
});
$db1 = null;
$db2 = null;
$db2 = Company::on('db-ninja-02')->get();
$db2->each(function ($company){
$db1 = Company::on('db-ninja-01a')->find($company->id);
if($db1)
{
$db1->subdomain = $company->subdomain;
$db1->save();
}
});
}
}

View File

@ -28,6 +28,7 @@ class CompanySettings extends BaseSettings
public $lock_invoices = 'off'; //off,when_sent,when_paid //@implemented public $lock_invoices = 'off'; //off,when_sent,when_paid //@implemented
public $enable_client_portal_tasks = false; //@ben to implement public $enable_client_portal_tasks = false; //@ben to implement
public $show_all_tasks_client_portal = 'all'; // all, uninvoiced, invoiced
public $enable_client_portal_password = false; //@implemented public $enable_client_portal_password = false; //@implemented
public $enable_client_portal = true; //@implemented public $enable_client_portal = true; //@implemented
public $enable_client_portal_dashboard = false; // @TODO There currently is no dashboard so this is pending public $enable_client_portal_dashboard = false; // @TODO There currently is no dashboard so this is pending
@ -268,6 +269,7 @@ class CompanySettings extends BaseSettings
public $hide_empty_columns_on_pdf = false; public $hide_empty_columns_on_pdf = false;
public static $casts = [ public static $casts = [
'show_all_tasks_client_portal' => 'string',
'entity_send_time' => 'int', 'entity_send_time' => 'int',
'shared_invoice_credit_counter' => 'bool', 'shared_invoice_credit_counter' => 'bool',
'reply_to_name' => 'string', 'reply_to_name' => 'string',

View File

@ -27,4 +27,7 @@ class PaymentMethodMeta
/** @var int */ /** @var int */
public $type; public $type;
/** @var string */
public $state;
} }

View File

@ -1,4 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\Controllers\Auth; namespace App\Http\Controllers\Auth;

View File

@ -179,8 +179,6 @@ class LoginController extends BaseController
$user = $this->guard()->user(); $user = $this->guard()->user();
event(new UserLoggedIn($user, $user->account->default_company, Ninja::eventVars($user->id)));
//2FA //2FA
if($user->google_2fa_secret && $request->has('one_time_password')) if($user->google_2fa_secret && $request->has('one_time_password'))
{ {
@ -226,6 +224,8 @@ class LoginController extends BaseController
if(Ninja::isHosted() && !$cu->first()->is_owner && !$user->account->isEnterpriseClient()) if(Ninja::isHosted() && !$cu->first()->is_owner && !$user->account->isEnterpriseClient())
return response()->json(['message' => 'Pro / Free accounts only the owner can log in. Please upgrade'], 403); return response()->json(['message' => 'Pro / Free accounts only the owner can log in. Please upgrade'], 403);
event(new UserLoggedIn($user, $user->account->default_company, Ninja::eventVars($user->id)));
return $this->timeConstrainedResponse($cu); return $this->timeConstrainedResponse($cu);
@ -300,7 +300,6 @@ class LoginController extends BaseController
$cu = CompanyUser::query() $cu = CompanyUser::query()
->where('user_id', $company_token->user_id); ->where('user_id', $company_token->user_id);
$cu->first()->account->companies->each(function ($company) use($cu, $request){ $cu->first()->account->companies->each(function ($company) use($cu, $request){
if($company->tokens()->where('is_system', true)->count() == 0) if($company->tokens()->where('is_system', true)->count() == 0)
@ -309,7 +308,6 @@ class LoginController extends BaseController
} }
}); });
if($request->has('current_company') && $request->input('current_company') == 'true') if($request->has('current_company') && $request->input('current_company') == 'true')
$cu->where("company_id", $company_token->company_id); $cu->where("company_id", $company_token->company_id);
@ -361,6 +359,9 @@ class LoginController extends BaseController
if ($existing_user = MultiDB::hasUser($query)) { if ($existing_user = MultiDB::hasUser($query)) {
if(!$existing_user->account)
return response()->json(['message' => 'User exists, but not attached to any companies! Orphaned user!'], 400);
Auth::login($existing_user, true); Auth::login($existing_user, true);
$existing_user->setCompany($existing_user->account->default_company); $existing_user->setCompany($existing_user->account->default_company);
@ -387,6 +388,9 @@ class LoginController extends BaseController
//If this is a result user/email combo - lets add their OAuth details details //If this is a result user/email combo - lets add their OAuth details details
if($existing_login_user = MultiDB::hasUser(['email' => $google->harvestEmail($user)])) if($existing_login_user = MultiDB::hasUser(['email' => $google->harvestEmail($user)]))
{ {
if(!$existing_login_user->account)
return response()->json(['message' => 'User exists, but not attached to any companies! Orphaned user!'], 400);
Auth::login($existing_login_user, true); Auth::login($existing_login_user, true);
$existing_login_user->setCompany($existing_login_user->account->default_company); $existing_login_user->setCompany($existing_login_user->account->default_company);
@ -422,6 +426,9 @@ class LoginController extends BaseController
if($existing_login_user = MultiDB::hasUser(['email' => $google->harvestEmail($user)])) if($existing_login_user = MultiDB::hasUser(['email' => $google->harvestEmail($user)]))
{ {
if(!$existing_login_user->account)
return response()->json(['message' => 'User exists, but not attached to any companies! Orphaned user!'], 400);
Auth::login($existing_login_user, true); Auth::login($existing_login_user, true);
$existing_login_user->setCompany($existing_login_user->account->default_company); $existing_login_user->setCompany($existing_login_user->account->default_company);

View File

@ -379,8 +379,6 @@ class BaseController extends Controller
'company.designs'=> function ($query) use ($created_at, $user) { 'company.designs'=> function ($query) use ($created_at, $user) {
$query->where('created_at', '>=', $created_at)->with('company'); $query->where('created_at', '>=', $created_at)->with('company');
if(!$user->isAdmin())
$query->where('designs.user_id', $user->id);
}, },
'company.documents'=> function ($query) use ($created_at, $user) { 'company.documents'=> function ($query) use ($created_at, $user) {
$query->where('created_at', '>=', $created_at); $query->where('created_at', '>=', $created_at);
@ -388,22 +386,14 @@ class BaseController extends Controller
'company.groups' => function ($query) use ($created_at, $user) { 'company.groups' => function ($query) use ($created_at, $user) {
$query->where('created_at', '>=', $created_at); $query->where('created_at', '>=', $created_at);
if(!$user->isAdmin())
$query->where('group_settings.user_id', $user->id);
}, },
'company.payment_terms'=> function ($query) use ($created_at, $user) { 'company.payment_terms'=> function ($query) use ($created_at, $user) {
$query->where('created_at', '>=', $created_at); $query->where('created_at', '>=', $created_at);
if(!$user->isAdmin())
$query->where('payment_terms.user_id', $user->id);
}, },
'company.tax_rates' => function ($query) use ($created_at, $user) { 'company.tax_rates' => function ($query) use ($created_at, $user) {
$query->where('created_at', '>=', $created_at); $query->where('created_at', '>=', $created_at);
if(!$user->isAdmin())
$query->where('tax_rates.user_id', $user->id);
}, },
'company.activities'=> function ($query) use($user) { 'company.activities'=> function ($query) use($user) {
@ -519,8 +509,6 @@ class BaseController extends Controller
'company.payment_terms'=> function ($query) use ($created_at, $user) { 'company.payment_terms'=> function ($query) use ($created_at, $user) {
$query->where('created_at', '>=', $created_at); $query->where('created_at', '>=', $created_at);
if(!$user->isAdmin())
$query->where('payment_terms.user_id', $user->id);
}, },
'company.products' => function ($query) use ($created_at, $user) { 'company.products' => function ($query) use ($created_at, $user) {
@ -561,9 +549,6 @@ class BaseController extends Controller
'company.tax_rates' => function ($query) use ($created_at, $user) { 'company.tax_rates' => function ($query) use ($created_at, $user) {
$query->where('created_at', '>=', $created_at); $query->where('created_at', '>=', $created_at);
if(!$user->isAdmin())
$query->where('tax_rates.user_id', $user->id);
}, },
'company.vendors'=> function ($query) use ($created_at, $user) { 'company.vendors'=> function ($query) use ($created_at, $user) {
$query->where('created_at', '>=', $created_at)->with('contacts', 'documents'); $query->where('created_at', '>=', $created_at)->with('contacts', 'documents');
@ -575,9 +560,6 @@ class BaseController extends Controller
'company.expense_categories'=> function ($query) use ($created_at, $user) { 'company.expense_categories'=> function ($query) use ($created_at, $user) {
$query->where('created_at', '>=', $created_at); $query->where('created_at', '>=', $created_at);
if(!$user->isAdmin())
$query->where('expense_categories.user_id', $user->id);
}, },
'company.task_statuses'=> function ($query) use ($created_at, $user) { 'company.task_statuses'=> function ($query) use ($created_at, $user) {
$query->where('created_at', '>=', $created_at); $query->where('created_at', '>=', $created_at);

View File

@ -89,6 +89,7 @@ class InvoiceController extends Controller
{ {
$invoices = Invoice::whereIn('id', $ids) $invoices = Invoice::whereIn('id', $ids)
->whereClientId(auth()->user()->client->id) ->whereClientId(auth()->user()->client->id)
->withTrashed()
->get(); ->get();
//filter invoices which are payable //filter invoices which are payable
@ -167,7 +168,8 @@ class InvoiceController extends Controller
if ($invoices->count() == 1) { if ($invoices->count() == 1) {
$invoice = $invoices->first(); $invoice = $invoices->first();
$invitation = $invoice->invitations->first(); $invitation = $invoice->invitations->first();
$file = $invoice->pdf_file_path($invitation); //$file = $invoice->pdf_file_path($invitation);
$file = $invoice->service()->getInvoicePdf(auth()->user());
return response()->download($file, basename($file), ['Cache-Control:' => 'no-cache'])->deleteFileAfterSend(true);; return response()->download($file, basename($file), ['Cache-Control:' => 'no-cache'])->deleteFileAfterSend(true);;
} }

View File

@ -95,7 +95,7 @@ class PaymentController extends Controller
*/ */
$payable_invoices = collect($request->payable_invoices); $payable_invoices = collect($request->payable_invoices);
$invoices = Invoice::whereIn('id', $this->transformKeys($payable_invoices->pluck('invoice_id')->toArray()))->get(); $invoices = Invoice::whereIn('id', $this->transformKeys($payable_invoices->pluck('invoice_id')->toArray()))->withTrashed()->get();
$invoices->each(function($invoice){ $invoices->each(function($invoice){
$invoice->service()->removeUnpaidGatewayFees()->save(); $invoice->service()->removeUnpaidGatewayFees()->save();

View File

@ -51,7 +51,8 @@ class PaymentMethodController extends Controller
$gateway = $this->getClientGateway(); $gateway = $this->getClientGateway();
$data['gateway'] = $gateway; $data['gateway'] = $gateway;
$data['client'] = auth()->user()->client;
return $gateway return $gateway
->driver(auth()->user()->client) ->driver(auth()->user()->client)
->setPaymentMethod($request->query('method')) ->setPaymentMethod($request->query('method'))
@ -91,9 +92,9 @@ class PaymentMethodController extends Controller
public function verify(ClientGatewayToken $payment_method) public function verify(ClientGatewayToken $payment_method)
{ {
$gateway = $this->getClientGateway(); // $gateway = $this->getClientGateway();
return $gateway return $payment_method->gateway
->driver(auth()->user()->client) ->driver(auth()->user()->client)
->setPaymentMethod(request()->query('method')) ->setPaymentMethod(request()->query('method'))
->verificationView($payment_method); ->verificationView($payment_method);
@ -101,9 +102,9 @@ class PaymentMethodController extends Controller
public function processVerification(Request $request, ClientGatewaytoken $payment_method) public function processVerification(Request $request, ClientGatewaytoken $payment_method)
{ {
$gateway = $this->getClientGateway(); // $gateway = $this->getClientGateway();
return $gateway return $payment_method->gateway
->driver(auth()->user()->client) ->driver(auth()->user()->client)
->setPaymentMethod(request()->query('method')) ->setPaymentMethod(request()->query('method'))
->processVerification($request, $payment_method); ->processVerification($request, $payment_method);
@ -117,9 +118,9 @@ class PaymentMethodController extends Controller
*/ */
public function destroy(ClientGatewayToken $payment_method) public function destroy(ClientGatewayToken $payment_method)
{ {
$gateway = $this->getClientGateway(); // $gateway = $this->getClientGateway();
$gateway $payment_method->gateway
->driver(auth()->user()->client) ->driver(auth()->user()->client)
->setPaymentMethod(request()->query('method')) ->setPaymentMethod(request()->query('method'))
->detach($payment_method); ->detach($payment_method);

View File

@ -7,7 +7,7 @@
* *
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
* *
* @license https://opensource.org/licenses/AAL * @license https://www.elastic.co/licensing/elastic-license
*/ */
namespace App\Http\Controllers\ClientPortal; namespace App\Http\Controllers\ClientPortal;

View File

@ -123,8 +123,8 @@ class CompanyUserController extends BaseController
if (auth()->user()->isAdmin()) { if (auth()->user()->isAdmin()) {
$company_user->fill($request->input('company_user')); $company_user->fill($request->input('company_user'));
} else { } else {
$company_user->fill($request->input('company_user')['settings']); $company_user->settings = $request->input('company_user')['settings'];
$company_user->fill($request->input('company_user')['notifications']); $company_user->notifications = $request->input('company_user')['notifications'];
} }
$company_user->save(); $company_user->save();

View File

@ -1,5 +1,4 @@
<?php <?php
/** /**
* Invoice Ninja (https://invoiceninja.com). * Invoice Ninja (https://invoiceninja.com).
* *
@ -98,6 +97,7 @@ class StripeConnectController extends BaseController
$company_gateway->gateway_key = 'd14dd26a47cecc30fdd65700bfb67b34'; $company_gateway->gateway_key = 'd14dd26a47cecc30fdd65700bfb67b34';
$company_gateway->fees_and_limits = $fees_and_limits; $company_gateway->fees_and_limits = $fees_and_limits;
$company_gateway->setConfig([]); $company_gateway->setConfig([]);
$company_gateway->token_billing = 'always';
// $company_gateway->save(); // $company_gateway->save();
$payload = [ $payload = [

View File

@ -29,7 +29,6 @@ class StripeController extends BaseController
} }
return response()->json(['message' => 'Unauthorized'], 403); return response()->json(['message' => 'Unauthorized'], 403);
} }
@ -44,7 +43,6 @@ class StripeController extends BaseController
return response()->json(['message' => 'Processing'], 200); return response()->json(['message' => 'Processing'], 200);
} }
return response()->json(['message' => 'Unauthorized'], 403); return response()->json(['message' => 'Unauthorized'], 403);
} }

View File

@ -76,7 +76,7 @@ class SendingController extends Controller
} }
Mail::to(config('ninja.contact.ninja_official_contact')) Mail::to(config('ninja.contact.ninja_official_contact'))
->send(new SupportMessageSent($request->message, $send_logs)); ->send(new SupportMessageSent($request->input('message'), $send_logs));
return response()->json([ return response()->json([
'success' => true, 'success' => true,

View File

@ -0,0 +1,54 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\Controllers;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\CompanyGateway;
use App\Models\User;
use App\PaymentDrivers\WePayPaymentDriver;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
class WePayController extends BaseController
{
use MakesHash;
/**
* Initialize WePay Signup.
*/
public function signup(string $token)
{
$hash = Cache::get($token);
MultiDB::findAndSetDbByCompanyKey($hash['company_key']);
$user = User::findOrFail($hash['user_id']);
$company = Company::where('company_key', $hash['company_key'])->firstOrFail();
$data['user_id'] = $user->id;
$data['company'] = $company;
$wepay_driver = new WePayPaymentDriver(new CompanyGateway, null, null);
return $wepay_driver->setup($data);
}
public function finished()
{
return render('gateways.wepay.signup.finished');
}
}

View File

@ -0,0 +1,201 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\Livewire;
use App\DataMapper\FeesAndLimits;
use App\Factory\CompanyGatewayFactory;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use App\Models\User;
use App\PaymentDrivers\WePayPaymentDriver;
use Illuminate\Support\Facades\Hash;
use Livewire\Component;
use WePay;
class WepaySignup extends Component
{
public $user;
public $user_id;
public $company_key;
public $first_name;
public $last_name;
public $email;
public $company_name;
public $country;
public $ach;
public $wepay_payment_tos_agree;
public $debit_cards;
public $terms;
public $privacy_policy;
public $saved;
public $company;
protected $rules = [
'first_name' => ['required'],
'last_name' => ['required'],
'email' => ['required', 'email'],
'company_name' => ['required'],
'country' => ['required'],
'ach' => ['sometimes'],
'wepay_payment_tos_agree' => ['accepted'],
'debit_cards' => ['sometimes'],
];
public function mount()
{
MultiDB::setDb($this->company->db);
$user = User::find($this->user_id);
$this->company = Company::where('company_key', $this->company->company_key)->first();
$this->fill([
'wepay_payment_tos_agree' => '',
'ach' => '',
'country' => 'US',
'user' => $user,
'first_name' => $user->first_name,
'last_name' => $user->last_name,
'email' => $user->email,
'company_name' => $this->company->present()->name(),
'saved' => ctrans('texts.confirm'),
'terms' => '<a href="https://go.wepay.com/terms-of-service" target="_blank">'.ctrans('texts.terms_of_service').'</a>',
'privacy_policy' => '<a href="https://go.wepay.com/privacy-policy" target="_blank">'.ctrans('texts.privacy_policy').'</a>',
]);
}
public function render()
{
return render('gateways.wepay.signup.wepay-signup');
}
public function submit()
{
$data = $this->validate($this->rules);
//need to create or get a new WePay CompanyGateway
$cg = CompanyGateway::where('gateway_key', '8fdeed552015b3c7b44ed6c8ebd9e992')
->where('company_id', $this->company->id)
->firstOrNew();
if(!$cg->id) {
$fees_and_limits = new \stdClass;
$fees_and_limits->{GatewayType::CREDIT_CARD} = new FeesAndLimits;
$fees_and_limits->{GatewayType::BANK_TRANSFER} = new FeesAndLimits;
$cg = CompanyGatewayFactory::create($this->company->id, $this->user->id);
$cg->gateway_key = '8fdeed552015b3c7b44ed6c8ebd9e992';
$cg->require_cvv = false;
$cg->require_billing_address = false;
$cg->require_shipping_address = false;
$cg->update_details = false;
$cg->config = encrypt(config('ninja.testvars.checkout'));
$cg->fees_and_limits = $fees_and_limits;
$cg->token_billing = 'always';
$cg->save();
}
$this->saved = ctrans('texts.processing');
$wepay_driver = new WePayPaymentDriver($cg, null, null);
$wepay = $wepay_driver->init()->wepay;
$user_details = [
'client_id' => config('ninja.wepay.client_id'),
'client_secret' => config('ninja.wepay.client_secret'),
'email' => $data['email'],
'first_name' => $data['first_name'],
'last_name' => $data['last_name'],
'original_ip' => request()->ip(),
'original_device' => request()->server('HTTP_USER_AGENT'),
'tos_acceptance_time' => time(),
'redirect_uri' => route('wepay.finished'),
'scope' => 'manage_accounts,collect_payments,view_user,preapprove_payments,send_money',
];
$wepay_user = $wepay->request('user/register/', $user_details);
$access_token = $wepay_user->access_token;
$access_token_expires = $wepay_user->expires_in ? (time() + $wepay_user->expires_in) : null;
$wepay = new WePay($access_token);
$account_details = [
'name' => $data['company_name'],
'description' => ctrans('texts.wepay_account_description'),
'theme_object' => json_decode('{"name":"Invoice Ninja","primary_color":"0b4d78","secondary_color":"0b4d78","background_color":"f8f8f8","button_color":"33b753"}'),
'callback_uri' => route('payment_webhook', ['company_key' => $this->company->company_key, 'company_gateway_id' => $cg->hashed_id]),
'rbits' => $this->company->rBits(),
'country' => $data['country'],
];
if ($data['country'] == 'CA') {
$account_details['currencies'] = ['CAD'];
$account_details['country_options'] = ['debit_opt_in' => boolval($data['debit_cards'])];
} elseif ($data['country'] == 'GB') {
$account_details['currencies'] = ['GBP'];
}
$wepay_account = $wepay->request('account/create/', $account_details);
try {
$wepay->request('user/send_confirmation/', []);
$confirmation_required = true;
} catch (\WePayException $ex) {
if ($ex->getMessage() == 'This access_token is already approved.') {
$confirmation_required = false;
} else {
request()->session()->flash('message', $ex->getMessage());
}
nlog("failed in try catch ");
nlog($ex->getMessage());
}
$config = [
'userId' => $wepay_user->user_id,
'accessToken' => $access_token,
'tokenType' => $wepay_user->token_type,
'tokenExpires' => $access_token_expires,
'accountId' => $wepay_account->account_id,
'state' => $wepay_account->state,
'testMode' => config('ninja.wepay.environment') == 'staging',
'country' => $data['country'],
];
$cg->setConfig($config);
$cg->save();
if ($confirmation_required) {
request()->session()->flash('message', trans('texts.created_wepay_confirmation_required'));
} else {
$update_uri = $wepay->request('/account/get_update_uri', [
'account_id' => $wepay_account->account_id,
'redirect_uri' => config('ninja.app_url'),
]);
return redirect($update_uri->uri);
}
return redirect()->to('/wepay/finished');
}
}

View File

@ -55,8 +55,15 @@ class QueryLogging
//nlog($request->method().' - '.urldecode($request->url()).": $count queries - ".$time); //nlog($request->method().' - '.urldecode($request->url()).": $count queries - ".$time);
// if($count > 50) // if($count > 50)
//nlog($queries); //nlog($queries);
$ip = '';
LightLogs::create(new DbQuery($request->method(), urldecode($request->url()), $count, $time, request()->ip())) if(request()->header('Cf-Connecting-Ip'))
$ip = request()->header('Cf-Connecting-Ip');
else{
$ip = request()->ip();
}
LightLogs::create(new DbQuery($request->method(), urldecode($request->url()), $count, $time, $ip))
->batch(); ->batch();
} }

View File

@ -7,7 +7,7 @@
* *
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
* *
* @license https://opensource.org/licenses/AAL * @license https://www.elastic.co/licensing/elastic-license
*/ */
namespace App\Http\Requests\ClientPortal\Credits; namespace App\Http\Requests\ClientPortal\Credits;

View File

@ -7,7 +7,7 @@
* *
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
* *
* @license https://opensource.org/licenses/AAL * @license https://www.elastic.co/licensing/elastic-license
*/ */
namespace App\Http\Requests\ClientPortal\Invoices; namespace App\Http\Requests\ClientPortal\Invoices;

View File

@ -7,7 +7,7 @@
* *
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
* *
* @license https://opensource.org/licenses/AAL * @license https://www.elastic.co/licensing/elastic-license
*/ */
namespace App\Http\Requests\ClientPortal\Invoices; namespace App\Http\Requests\ClientPortal\Invoices;

View File

@ -7,7 +7,7 @@
* *
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
* *
* @license https://opensource.org/licenses/AAL * @license https://www.elastic.co/licensing/elastic-license
*/ */
namespace App\Http\Requests\ClientPortal\Quotes; namespace App\Http\Requests\ClientPortal\Quotes;

View File

@ -7,7 +7,7 @@
* *
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
* *
* @license https://opensource.org/licenses/AAL * @license https://www.elastic.co/licensing/elastic-license
*/ */
namespace App\Http\Requests\ClientPortal\Quotes; namespace App\Http\Requests\ClientPortal\Quotes;

View File

@ -7,7 +7,7 @@
* *
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
* *
* @license https://opensource.org/licenses/AAL * @license https://www.elastic.co/licensing/elastic-license
*/ */
namespace App\Http\Requests\ClientPortal\Quotes; namespace App\Http\Requests\ClientPortal\Quotes;

View File

@ -7,7 +7,7 @@
* *
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
* *
* @license https://opensource.org/licenses/AAL * @license https://www.elastic.co/licensing/elastic-license
*/ */
namespace App\Http\Requests\ClientPortal\RecurringInvoices; namespace App\Http\Requests\ClientPortal\RecurringInvoices;

View File

@ -30,7 +30,7 @@ class RegisterRequest extends FormRequest
'first_name' => ['required', 'string', 'max:255'], 'first_name' => ['required', 'string', 'max:255'],
'last_name' => ['required', 'string', 'max:255'], 'last_name' => ['required', 'string', 'max:255'],
'phone' => ['required', 'string', 'max:255'], 'phone' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email:rfc,dns', 'max:255', 'unique:client_contacts'], 'email' => ['required', 'string', 'email:rfc,dns', 'max:255'],
'password' => ['required', 'string', 'min:6', 'confirmed'], 'password' => ['required', 'string', 'min:6', 'confirmed'],
]; ];
} }

View File

@ -7,7 +7,7 @@
* *
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
* *
* @license https://opensource.org/licenses/AAL * @license https://www.elastic.co/licensing/elastic-license
*/ */
namespace App\Http\Requests\ClientPortal\Tasks; namespace App\Http\Requests\ClientPortal\Tasks;

View File

@ -484,7 +484,7 @@ class CompanyExport implements ShouldQueue
if(!Storage::disk(config('filesystems.default'))->exists($path)) if(!Storage::disk(config('filesystems.default'))->exists($path))
Storage::disk(config('filesystems.default'))->makeDirectory($path, 0775); Storage::disk(config('filesystems.default'))->makeDirectory($path, 0775);
$zip_path = public_path('storage/backups/'.$file_name); $zip_path = public_path('storage/backups/'.$file_name);
$zip = new \ZipArchive(); $zip = new \ZipArchive();

View File

@ -43,7 +43,7 @@ class RecurringInvoicesCron
nlog("Sending recurring invoices ".Carbon::now()->format('Y-m-d h:i:s')); nlog("Sending recurring invoices ".Carbon::now()->format('Y-m-d h:i:s'));
if (! config('ninja.db.multi_db_enabled')) { if (! config('ninja.db.multi_db_enabled')) {
$recurring_invoices = RecurringInvoice::whereDate('next_send_date', '<=', now()) $recurring_invoices = RecurringInvoice::where('next_send_date', '<=', now()->toDateTimeString())
->whereNotNull('next_send_date') ->whereNotNull('next_send_date')
->where('status_id', RecurringInvoice::STATUS_ACTIVE) ->where('status_id', RecurringInvoice::STATUS_ACTIVE)
->where('remaining_cycles', '!=', '0') ->where('remaining_cycles', '!=', '0')
@ -64,7 +64,7 @@ class RecurringInvoicesCron
foreach (MultiDB::$dbs as $db) { foreach (MultiDB::$dbs as $db) {
MultiDB::setDB($db); MultiDB::setDB($db);
$recurring_invoices = RecurringInvoice::whereDate('next_send_date', '<=', now()) $recurring_invoices = RecurringInvoice::where('next_send_date', '<=', now()->toDateTimeString())
->whereNotNull('next_send_date') ->whereNotNull('next_send_date')
->where('status_id', RecurringInvoice::STATUS_ACTIVE) ->where('status_id', RecurringInvoice::STATUS_ACTIVE)
->where('remaining_cycles', '!=', '0') ->where('remaining_cycles', '!=', '0')

View File

@ -214,12 +214,12 @@ class Import implements ShouldQueue
// if(Ninja::isHosted() && array_key_exists('ninja_tokens', $data)) // if(Ninja::isHosted() && array_key_exists('ninja_tokens', $data))
$this->processNinjaTokens($data['ninja_tokens']); $this->processNinjaTokens($data['ninja_tokens']);
$this->fixData();
$this->setInitialCompanyLedgerBalances(); $this->setInitialCompanyLedgerBalances();
// $this->fixClientBalances(); // $this->fixClientBalances();
$check_data = CheckCompanyData::dispatchNow($this->company, md5(time())); $check_data = CheckCompanyData::dispatchNow($this->company, md5(time()));
try{ try{
Mail::to($this->user->email, $this->user->name()) Mail::to($this->user->email, $this->user->name())
@ -247,6 +247,41 @@ class Import implements ShouldQueue
unlink($this->file_path); unlink($this->file_path);
} }
private function fixData()
{
$this->company->clients()->withTrashed()->where('is_deleted', 0)->cursor()->each(function ($client) {
$total_invoice_payments = 0;
$credit_total_applied = 0;
foreach ($client->invoices()->where('is_deleted', false)->where('status_id', '>', 1)->get() as $invoice) {
$total_amount = $invoice->payments()->where('is_deleted', false)->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment:: STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED])->get()->sum('pivot.amount');
$total_refund = $invoice->payments()->where('is_deleted', false)->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment:: STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED])->get()->sum('pivot.refunded');
$total_invoice_payments += ($total_amount - $total_refund);
}
// 10/02/21
foreach ($client->payments as $payment) {
$credit_total_applied += $payment->paymentables()->where('paymentable_type', App\Models\Credit::class)->get()->sum(\DB::raw('amount'));
}
if ($credit_total_applied < 0) {
$total_invoice_payments += $credit_total_applied;
}
if (round($total_invoice_payments, 2) != round($client->paid_to_date, 2)) {
$client->paid_to_date = $total_invoice_payments;
$client->save();
}
});
}
private function setInitialCompanyLedgerBalances() private function setInitialCompanyLedgerBalances()
{ {
Client::cursor()->each(function ($client) { Client::cursor()->each(function ($client) {
@ -1175,10 +1210,14 @@ class Import implements ShouldQueue
if($try_quote && array_key_exists('quotes', $this->ids) ) { if($try_quote && array_key_exists('quotes', $this->ids) ) {
$quote_id = $this->transformId('quotes', $resource['invoice_id']); try{
$entity = Quote::where('id', $quote_id)->withTrashed()->first(); $quote_id = $this->transformId('quotes', $resource['invoice_id']);
$exception = $e; $entity = Quote::where('id', $quote_id)->withTrashed()->first();
}
catch(\Exception $e){
nlog("i couldn't find the quote document {$resource['invoice_id']}, perhaps it is a quote?");
nlog($e->getMessage());
}
} }
if(!$entity) if(!$entity)
@ -1642,7 +1681,6 @@ class Import implements ShouldQueue
public function exec($method, $url, $data) public function exec($method, $url, $data)
{ {
nlog($this->token);
$client = new \GuzzleHttp\Client(['headers' => $client = new \GuzzleHttp\Client(['headers' =>
[ [

View File

@ -53,7 +53,9 @@ class ReminderJob implements ShouldQueue
private function processReminders() private function processReminders()
{ {
Invoice::whereDate('next_send_date', '<=', now()) nlog("Sending invoice reminders " . now()->format('Y-m-d h:i:s'));
Invoice::where('next_send_date', '<=', now()->toDateTimeString())
->where('is_deleted', 0) ->where('is_deleted', 0)
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
->where('balance', '>', 0) ->where('balance', '>', 0)

View File

@ -37,7 +37,8 @@ class MigrationCompleted extends Mailable
$data['company'] = $this->company->fresh(); $data['company'] = $this->company->fresh();
$data['whitelabel'] = $this->company->account->isPaid() ? true : false; $data['whitelabel'] = $this->company->account->isPaid() ? true : false;
$data['check_data'] = $this->check_data; $data['check_data'] = $this->check_data;
$data['logo'] = $this->company->present()->logo();
$result = $this->from(config('mail.from.address'), config('mail.from.name')) $result = $this->from(config('mail.from.address'), config('mail.from.name'))
->view('email.import.completed', $data); ->view('email.import.completed', $data);

View File

@ -13,13 +13,13 @@ class SupportMessageSent extends Mailable
{ {
// use Queueable, SerializesModels; // use Queueable, SerializesModels;
public $message; public $support_message;
public $send_logs; public $send_logs;
public function __construct($message, $send_logs) public function __construct($support_message, $send_logs)
{ {
$this->message = $message; $this->support_message = $support_message;
$this->send_logs = $send_logs; $this->send_logs = $send_logs;
} }
@ -52,18 +52,21 @@ class SupportMessageSent extends Mailable
$account = auth()->user()->account; $account = auth()->user()->account;
$plan = $account->plan ?: 'Self Hosted'; $plan = $account->plan ?: 'Free Self Hosted';
$company = auth()->user()->company(); $company = auth()->user()->company();
$user = auth()->user(); $user = auth()->user();
$subject = "Customer MSG {$user->present()->name} - [{$plan} - DB:{$company->db}]"; if(Ninja::isHosted())
$subject = "Hosted {$user->present()->name} - [{$plan} - DB:{$company->db}]";
else
$subject = "Self Host {$user->present()->name} - [{$plan} - DB:{$company->db}]";
return $this->from(config('mail.from.address'), config('mail.from.name')) return $this->from(config('mail.from.address'), config('mail.from.name'))
->replyTo($user->email, $user->present()->name()) ->replyTo($user->email, $user->present()->name())
->subject($subject) ->subject($subject)
->view('email.support.message', [ ->view('email.support.message', [
'message' => $this->message, 'support_message' => $this->support_message,
'system_info' => $system_info, 'system_info' => $system_info,
'laravel_log' => $log_lines, 'laravel_log' => $log_lines,
'logo' => $company->present()->logo(), 'logo' => $company->present()->logo(),

View File

@ -468,4 +468,39 @@ class Company extends BaseModel
{ {
return $this->slack_webhook_url; return $this->slack_webhook_url;
} }
public function rBits()
{
$user = $this->owner();
$data = [];
$data[] = $this->createRBit('business_name', 'user', ['business_name' => $this->present()->name()]);
$data[] = $this->createRBit('industry_code', 'user', ['industry_detail' => $this->industry ? $this->industry->name : '']);
$data[] = $this->createRBit('comment', 'partner_database', ['comment_text' => 'Logo image not present']);
$data[] = $this->createRBit('business_description', 'user', ['business_description' => $this->present()->size()]);
$data[] = $this->createRBit('person', 'user', ['name' => $user->present()->getFullName()]);
$data[] = $this->createRBit('email', 'user', ['email' => $user->email]);
$data[] = $this->createRBit('phone', 'user', ['phone' => $user->phone]);
$data[] = $this->createRBit('website_uri', 'user', ['uri' => $this->settings->website]);
$data[] = $this->createRBit('external_account', 'partner_database', ['is_partner_account' => 'yes', 'account_type' => 'Invoice Ninja', 'create_time' => time()]);
return $data;
}
private function createRBit($type, $source, $properties)
{
$data = new \stdClass;
$data->receive_time = time();
$data->type = $type;
$data->source = $source;
$data->properties = new \stdClass;
foreach ($properties as $key => $val) {
$data->properties->$key = $val;
}
return $data;
}
} }

View File

@ -95,6 +95,10 @@ class Gateway extends StaticModel
case 39: case 39:
return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]]; //Checkout return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]]; //Checkout
break; break;
case 49:
return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true],
GatewayType::BANK_TRANSFER => ['refund' => true, 'token_billing' => true]]; //WePay
break;
case 50: case 50:
return [ return [
GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true], GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true],

View File

@ -59,6 +59,8 @@ class Payment extends BaseModel
'date', 'date',
'transaction_reference', 'transaction_reference',
'number', 'number',
'exchange_currency_id',
'exchange_rate',
// 'is_manual', // 'is_manual',
'private_notes', 'private_notes',
'custom_value1', 'custom_value1',

View File

@ -136,21 +136,40 @@ class ClientPresenter extends EntityPresenter
return $str; return $str;
} }
// public function getCityState()
// {
// $settings = $this->entity->getMergedSettings();
// $country = false;
// if ($settings->country_id) {
// $country = Country::find($settings->country_id);
// }
// $swap = $country && $country->swap_postal_code;
// $city = e($settings->city ?: '');
// $state = e($settings->state ?: '');
// $postalCode = e($settings->postal_code ?: '');
// if ($city || $state || $postalCode) {
// return $this->cityStateZip($city, $state, $postalCode, $swap);
// } else {
// return false;
// }
// }
public function getCityState() public function getCityState()
{ {
$settings = $this->entity->getMergedSettings(); $client = $this->entity;
$country = false; $country = $client->country ?: false;
if ($settings->country_id) {
$country = Country::find($settings->country_id);
}
$swap = $country && $country->swap_postal_code; $swap = $country && $country->swap_postal_code;
$city = e($settings->city ?: ''); $city = e($client->city ?: '');
$state = e($settings->state ?: ''); $state = e($client->state ?: '');
$postalCode = e($settings->postal_code ?: ''); $postalCode = e($client->postal_code ?: '');
if ($city || $state || $postalCode) { if ($city || $state || $postalCode) {
return $this->cityStateZip($city, $state, $postalCode, $swap); return $this->cityStateZip($city, $state, $postalCode, $swap);

View File

@ -41,7 +41,7 @@ class CompanyPresenter extends EntityPresenter
else if(strlen($settings->company_logo) >= 1) else if(strlen($settings->company_logo) >= 1)
return url('') . $settings->company_logo; return url('') . $settings->company_logo;
else else
return 'https://www.invoiceninja.com/wp-content/uploads/2019/01/InvoiceNinja-Logo-Round-300x300.png'; return asset('images/new_logo.png');
} }
@ -101,9 +101,13 @@ class CompanyPresenter extends EntityPresenter
{ {
$settings = $this->entity->settings; $settings = $this->entity->settings;
return return
"SPC\n0200\n1\n{$user_iban}\nK\n{$this->name}\n{$settings->address1}\n{$settings->postal_code} {$settings->city}\n\n\nCH\n\n\n\n\n\n\n\n{$balance_due_raw}\n{$client_currency}\n\n\n\n\n\n\n\nNON\n\n{$invoice_number}\nEPD\n"; "SPC\n0200\n1\n{$user_iban}\nK\n{$this->name}\n{$settings->address1}\n{$settings->postal_code} {$settings->city}\n\n\nCH\n\n\n\n\n\n\n\n{$balance_due_raw}\n{$client_currency}\n\n\n\n\n\n\n\nNON\n\n{$invoice_number}\nEPD\n";
} }
public function size()
{
return $this->entity->size ? $this->entity->size->name : '';
}
} }

View File

@ -41,4 +41,35 @@ class InvoicePresenter extends EntityPresenter
return ''; return '';
} }
} }
public function rBits()
{
$properties = new \stdClass();
$properties->terms_text = $this->terms;
$properties->note = $this->public_notes;
$properties->itemized_receipt = [];
foreach ($this->line_items as $item) {
$properties->itemized_receipt[] = $this->itemRbits($item);
}
$data = new stdClass();
$data->receive_time = time();
$data->type = 'transaction_details';
$data->source = 'user';
$data->properties = $properties;
return [$data];
}
public function itemRbits($item)
{
$data = new stdClass();
$data->description = $item->notes;
$data->item_price = floatval($item->cost);
$data->quantity = floatval($item->quantity);
$data->amount = round($data->item_price * $data->quantity, 2);
return $data;
}
} }

View File

@ -26,4 +26,28 @@ class UserPresenter extends EntityPresenter
return $first_name.' '.$last_name; return $first_name.' '.$last_name;
} }
public function getDisplayName()
{
if ($this->getFullName()) {
return $this->getFullName();
} elseif ($this->entity->email) {
return $this->entity->email;
} else {
return ctrans('texts.guest');
}
}
/**
* @return string
*/
public function getFullName()
{
if ($this->entity->first_name || $this->entity->last_name) {
return $this->entity->first_name.' '.$this->entity->last_name;
} else {
return '';
}
}
} }

View File

@ -66,6 +66,8 @@ class SystemLog extends Model
const TYPE_AUTHORIZE = 305; const TYPE_AUTHORIZE = 305;
const TYPE_CUSTOM = 306; const TYPE_CUSTOM = 306;
const TYPE_BRAINTREE = 307; const TYPE_BRAINTREE = 307;
const TYPE_WEPAY = 309;
const TYPE_QUOTA_EXCEEDED = 400; const TYPE_QUOTA_EXCEEDED = 400;
const TYPE_UPSTREAM_FAILURE = 401; const TYPE_UPSTREAM_FAILURE = 401;

View File

@ -160,6 +160,17 @@ class BaseDriver extends AbstractPaymentDriver
{ {
} }
/**
* Detaches a payment method from the gateway
*
* @param ClientGatewayToken $token The gateway token
* @return bool boolean response
*/
public function detach(ClientGatewayToken $token)
{
return true;
}
/** /**
* Set the inbound request payment method type for access. * Set the inbound request payment method type for access.
* *
@ -188,7 +199,7 @@ class BaseDriver extends AbstractPaymentDriver
public function attachInvoices(Payment $payment, PaymentHash $payment_hash): Payment public function attachInvoices(Payment $payment, PaymentHash $payment_hash): Payment
{ {
$paid_invoices = $payment_hash->invoices(); $paid_invoices = $payment_hash->invoices();
$invoices = Invoice::whereIn('id', $this->transformKeys(array_column($paid_invoices, 'invoice_id')))->get(); $invoices = Invoice::whereIn('id', $this->transformKeys(array_column($paid_invoices, 'invoice_id')))->withTrashed()->get();
$payment->invoices()->sync($invoices); $payment->invoices()->sync($invoices);
$invoices->each(function ($invoice) use ($payment) { $invoices->each(function ($invoice) use ($payment) {

View File

@ -167,7 +167,7 @@ class ACH
return $this->processUnsuccessfulPayment($state); return $this->processUnsuccessfulPayment($state);
} catch (Exception $e) { } catch (Exception $e) {
if ($e instanceof CardException) { if ($e instanceof CardException) {
return redirect()->route('client.payment_methods.verification', ['id' => ClientGatewayToken::first()->hashed_id, 'method' => GatewayType::BANK_TRANSFER]); return redirect()->route('client.payment_methods.verification', ['payment_method' => ClientGatewayToken::first()->hashed_id, 'method' => GatewayType::BANK_TRANSFER]);
} }
throw new PaymentFailed($e->getMessage(), $e->getCode()); throw new PaymentFailed($e->getMessage(), $e->getCode());

View File

@ -47,164 +47,5 @@ class Account
]); ]);
} }
/*** If this is a new account (ie there is no account_id in company_gateways.config, the we need to create an account as below.
///
// $stripe = new \Stripe\StripeClient(
// 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
// );
// $stripe->accounts->create([
// 'type' => 'standard',
// 'country' => 'US', //if we have it - inject
// 'email' => 'jenny.rosen@example.com', //if we have it - inject
// ]);
///
//response
//******************* We should store the 'id' as a property in the config with the key `account_id`
/**
* {
"id": "acct_1032D82eZvKYlo2C",
"object": "account",
"business_profile": {
"mcc": null,
"name": "Stripe.com",
"product_description": null,
"support_address": null,
"support_email": null,
"support_phone": null,
"support_url": null,
"url": null
},
"capabilities": {
"card_payments": "active",
"transfers": "active"
},
"charges_enabled": false,
"country": "US",
"default_currency": "usd",
"details_submitted": false,
"email": "site@stripe.com",
"metadata": {},
"payouts_enabled": false,
"requirements": {
"current_deadline": null,
"currently_due": [
"business_profile.product_description",
"business_profile.support_phone",
"business_profile.url",
"external_account",
"tos_acceptance.date",
"tos_acceptance.ip"
],
"disabled_reason": "requirements.past_due",
"errors": [],
"eventually_due": [
"business_profile.product_description",
"business_profile.support_phone",
"business_profile.url",
"external_account",
"tos_acceptance.date",
"tos_acceptance.ip"
],
"past_due": [],
"pending_verification": []
},
"settings": {
"bacs_debit_payments": {},
"branding": {
"icon": null,
"logo": null,
"primary_color": null,
"secondary_color": null
},
"card_issuing": {
"tos_acceptance": {
"date": null,
"ip": null
}
},
"card_payments": {
"decline_on": {
"avs_failure": true,
"cvc_failure": false
},
"statement_descriptor_prefix": null
},
"dashboard": {
"display_name": "Stripe.com",
"timezone": "US/Pacific"
},
"payments": {
"statement_descriptor": null,
"statement_descriptor_kana": null,
"statement_descriptor_kanji": null
},
"payouts": {
"debit_negative_balances": true,
"schedule": {
"delay_days": 7,
"interval": "daily"
},
"statement_descriptor": null
},
"sepa_debit_payments": {}
},
"type": "standard"
}
*/
//At this stage we have an account, so we need to generate the account link
//then create the account link
// now we start the stripe onboarding flow
// https://stripe.com/docs/api/account_links/object
//
/**
* $stripe = new \Stripe\StripeClient(
'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
);
$stripe->accountLinks->create([
'account' => 'acct_1032D82eZvKYlo2C',
'refresh_url' => 'https://example.com/reauth',
'return_url' => 'https://example.com/return',
'type' => 'account_onboarding',
]);
*/
/**
* Response =
* {
"object": "account_link",
"created": 1618869558,
"expires_at": 1618869858,
"url": "https://connect.stripe.com/setup/s/9BhFaPdfseRF"
}
*/
//The users account may not be active yet, we need to pull the account back and check for the property `charges_enabled`
//
//
// What next?
//
// Now we need to create a superclass of the StripePaymentDriver, i believe the only thing we need to change is the way we initialize the gateway..
/**
*
\Stripe\Stripe::setApiKey("{{PLATFORM_SECRET_KEY}}"); <--- platform secret key = Invoice Ninja secret key
\Stripe\Customer::create(
["email" => "person@example.edu"],
["stripe_account" => "{{CONNECTED_STRIPE_ACCOUNT_ID}}"] <------ company_gateway.config.account_id
);
*/
} }

View File

@ -0,0 +1,265 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\PaymentDrivers\WePay;
use App\Exceptions\PaymentFailed;
use App\Models\ClientGatewayToken;
use App\Models\GatewayType;
use App\Models\Payment;
use App\PaymentDrivers\WePayPaymentDriver;
use App\PaymentDrivers\WePay\WePayCommon;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class ACH
{
use MakesHash;
use WePayCommon;
public $wepay_payment_driver;
public function __construct(WePayPaymentDriver $wepay_payment_driver)
{
$this->wepay_payment_driver = $wepay_payment_driver;
}
public function authorizeView($data)
{
$data['gateway'] = $this->wepay_payment_driver;
return render('gateways.wepay.authorize.bank_transfer', $data);
}
public function authorizeResponse($request)
{
//https://developer.wepay.com/api/api-calls/credit_card#authorize
$data = $request->all();
// authorize the credit card
nlog($data);
/*
'_token' => '1Fk5CRj34up5ntKPvrFyMIAJhDdUNF3boqT3iIN3',
'company_gateway_id' => '39',
'payment_method_id' => '1',
'gateway_response' => NULL,
'is_default' => NULL,
'credit_card_id' => '180642154638',
'q' => '/client/payment_methods',
'method' => '1',
*/
$response = $this->wepay_payment_driver->wepay->request('payment_bank/persist', [
'client_id' => config('ninja.wepay.client_id'),
'client_secret' => config('ninja.wepay.client_secret'),
'payment_bank_id' => (int)$data['bank_account_id'],
]);
// display the response
// nlog($response);
if(in_array($response->state, ['new', 'pending', 'authorized'])){
$this->storePaymentMethod($response, GatewayType::BANK_TRANSFER);
return redirect()->route('client.payment_methods.index');
}
throw new PaymentFailed("There was a problem adding this payment method.", 400);
/*
{
"payment_bank_id": 12345,
"bank_name": "Wells Fargo",
"account_last_four": "6789",
"state": "authorized"
}
state options: new, pending, authorized, disabled.
*/
}
/* If the bank transfer token is PENDING - we need to verify!! */
//
public function verificationView(ClientGatewayToken $token)
{
$this->wepay_payment_driver->init();
$data = [
'token' => $token,
'gateway' => $this->wepay_payment_driver,
];
return render('gateways.wepay.authorize.verify', $data);
}
/**
{
"client_id": 1234,
"client_secret": "b1fc2f68-4d1f-4a",
"payment_bank_id": 12345,
"type": "microdeposits",
"microdeposits": [
8,
12
]
}
*/
public function processVerification(Request $request, ClientGatewayToken $token)
{
$transactions = $request->input('transactions');
$transformed_transactions = [];
foreach($transactions as $transaction)
$transformed_transactions[] = (int)$transaction;
try {
$response = $this->wepay_payment_driver->wepay->request('payment_bank/verify', [
'client_id' => config('ninja.wepay.client_id'),
'client_secret' => config('ninja.wepay.client_secret'),
'payment_bank_id' => $token->token,
'type' => 'microdeposits',
'microdeposits' => $transformed_transactions,
]);
}
catch(\Exception $e){
return redirect()->route('client.payment_methods.verification', ['payment_method' => $token->hashed_id, 'method' => GatewayType::BANK_TRANSFER])
->with('error', $e->getMessage());
}
/*
{
"payment_bank_id": 12345,
"bank_name": "Wells Fargo",
"account_last_four": "6789",
"state": "authorized"
}
*/
nlog($response);
//$meta = $token->meta;
if($response->state == "authorized")
{
$meta = $token->meta;
$meta->state = $response->state;
$token->meta;
$token->save();
return redirect()->route('client.payment_methods.index');
}
else{
return redirect()->route('client.payment_methods.verification', ['payment_method' => $token->hashed_id, 'method' => GatewayType::BANK_TRANSFER])
->with('error', ctrans('texts.verification_failed'));
}
}
///////////////////////////////////////////////////////////////////////////////////////
public function paymentView(array $data)
{
$data['gateway'] = $this->wepay_payment_driver;
$data['currency'] = $this->wepay_payment_driver->client->getCurrencyCode();
$data['payment_method_id'] = GatewayType::BANK_TRANSFER;
$data['amount'] = $data['total']['amount_with_fee'];
return render('gateways.wepay.bank_transfer', $data);
}
public function paymentResponse($request)
{
nlog($request->all());
$token = ClientGatewayToken::find($this->decodePrimaryKey($request->input('source')));
$token_meta = $token->meta;
if($token_meta->state != "authorized")
return redirect()->route('client.payment_methods.verification', ['payment_method' => $token->hashed_id, 'method' => GatewayType::BANK_TRANSFER]);
$response = $this->wepay_payment_driver->wepay->request('checkout/create', array(
// 'callback_uri' => route('payment_webhook', ['company_key' => $this->wepay_payment_driver->company_gateway->company->company_key, 'company_gateway_id' => $this->wepay_payment_driver->company_gateway->hashed_id]),
'unique_id' => Str::random(40),
'account_id' => $this->wepay_payment_driver->company_gateway->getConfigField('accountId'),
'amount' => $this->wepay_payment_driver->payment_hash->data->amount_with_fee,
'currency' => $this->wepay_payment_driver->client->getCurrencyCode(),
'short_description' => 'A vacation home rental',
'type' => 'goods',
'payment_method' => array(
'type' => 'payment_bank',
'payment_bank' => array(
'id' => $token->token
)
)
));
/* Merge all data and store in the payment hash*/
$state = [
'server_response' => $response,
'payment_hash' => $request->payment_hash,
];
$state = array_merge($state, $request->all());
$this->wepay_payment_driver->payment_hash->data = array_merge((array) $this->wepay_payment_driver->payment_hash->data, $state);
$this->wepay_payment_driver->payment_hash->save();
if(in_array($response->state, ['authorized', 'captured'])){
//success
nlog("success");
$payment_status = $response->state == 'authorized' ? Payment::STATUS_COMPLETED : Payment::STATUS_PENDING;
return $this->processSuccessfulPayment($response, $payment_status, GatewayType::BANK_TRANSFER);
}
if(in_array($response->state, ['released', 'cancelled', 'failed', 'expired'])){
//some type of failure
nlog("failure");
$payment_status = $response->state == 'cancelled' ? Payment::STATUS_CANCELLED : Payment::STATUS_FAILED;
$this->processUnSuccessfulPayment($response, $payment_status);
}
}
private function storePaymentMethod($response, $payment_method_id)
{
$payment_meta = new \stdClass;
$payment_meta->exp_month = (string) '';
$payment_meta->exp_year = (string) '';
$payment_meta->brand = (string) $response->bank_name;
$payment_meta->last4 = (string) $response->account_last_four;
$payment_meta->type = GatewayType::BANK_TRANSFER;
$payment_meta->state = $response->state;
$data = [
'payment_meta' => $payment_meta,
'token' => $response->payment_bank_id,
'payment_method_id' => $payment_method_id,
];
$this->wepay_payment_driver->storeGatewayToken($data);
}
}

View File

@ -0,0 +1,281 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\PaymentDrivers\WePay;
use App\Exceptions\PaymentFailed;
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
use App\Jobs\Mail\PaymentFailureMailer;
use App\Jobs\Util\SystemLogger;
use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\WePayPaymentDriver;
use App\PaymentDrivers\WePay\WePayCommon;
use Illuminate\Support\Str;
class CreditCard
{
use WePayCommon;
public $wepay_payment_driver;
public function __construct(WePayPaymentDriver $wepay_payment_driver)
{
$this->wepay_payment_driver = $wepay_payment_driver;
}
public function authorizeView($data)
{
$data['gateway'] = $this->wepay_payment_driver;
return render('gateways.wepay.authorize.authorize', $data);
}
public function authorizeResponse($request)
{
//https://developer.wepay.com/api/api-calls/credit_card#authorize
$data = $request->all();
// authorize the credit card
nlog($data);
/*
'_token' => '1Fk5CRj34up5ntKPvrFyMIAJhDdUNF3boqT3iIN3',
'company_gateway_id' => '39',
'payment_method_id' => '1',
'gateway_response' => NULL,
'is_default' => NULL,
'credit_card_id' => '180642154638',
'q' => '/client/payment_methods',
'method' => '1',
*/
$response = $this->wepay_payment_driver->wepay->request('credit_card/authorize', array(
'client_id' => config('ninja.wepay.client_id'),
'client_secret' => config('ninja.wepay.client_secret'),
'credit_card_id' => (int)$data['credit_card_id'],
));
// display the response
// nlog($response);
if(in_array($response->state, ['new', 'authorized'])){
$this->storePaymentMethod($response, GatewayType::CREDIT_CARD);
return redirect()->route('client.payment_methods.index');
}
throw new PaymentFailed("There was a problem adding this payment method.", 400);
/*
[credit_card_id] => 348084962473
[credit_card_name] => Visa xxxxxx4018
[state] => authorized
[user_name] => Joey Diaz
[email] => user@example.com
[create_time] => 1623798172
[expiration_month] => 10
[expiration_year] => 2023
[last_four] => 4018
[input_source] => card_keyed
[virtual_terminal_mode] => none
[card_on_file] =>
[recurring] =>
[cvv_provided] => 1
[auto_update] =>
*/
}
public function paymentView(array $data)
{
$data['gateway'] = $this->wepay_payment_driver;
$data['description'] = ctrans('texts.invoices') . ': ' . collect($data['invoices'])->pluck('invoice_number');
return render('gateways.wepay.credit_card.pay', $data);
}
public function paymentResponse(PaymentResponseRequest $request)
{
nlog("payment response");
//it could be an existing token or a new credit_card_id that needs to be converted into a wepay token
if($request->has('credit_card_id') && $request->input('credit_card_id'))
{
nlog("authorize the card first!");
$response = $this->wepay_payment_driver->wepay->request('credit_card/authorize', array(
// 'callback_uri' => route('payment_webhook', ['company_key' => $this->wepay_payment_driver->company_gateway->company->company_key, 'company_gateway_id' => $this->wepay_payment_driver->company_gateway->hashed_id]),
'client_id' => config('ninja.wepay.client_id'),
'client_secret' => config('ninja.wepay.client_secret'),
'credit_card_id' => (int)$request->input('credit_card_id'),
));
$credit_card_id = (int)$response->credit_card_id;
if(in_array($response->state, ['new', 'authorized']) && boolval($request->input('store_card'))){
$this->storePaymentMethod($response, GatewayType::CREDIT_CARD);
}
}
else {
$credit_card_id = (int)$request->input('token');
}
// USD, CAD, and GBP.
nlog($request->all());
// charge the credit card
$response = $this->wepay_payment_driver->wepay->request('checkout/create', array(
// 'callback_uri' => route('payment_webhook', ['company_key' => $this->wepay_payment_driver->company_gateway->company->company_key, 'company_gateway_id' => $this->wepay_payment_driver->company_gateway->hashed_id]),
'unique_id' => Str::random(40),
'account_id' => $this->wepay_payment_driver->company_gateway->getConfigField('accountId'),
'amount' => $this->wepay_payment_driver->payment_hash->data->amount_with_fee,
'currency' => $this->wepay_payment_driver->client->getCurrencyCode(),
'short_description' => 'A vacation home rental',
'type' => 'goods',
'payment_method' => array(
'type' => 'credit_card',
'credit_card' => array(
'id' => $credit_card_id
)
)
));
/* Merge all data and store in the payment hash*/
$state = [
'server_response' => $response,
'payment_hash' => $request->payment_hash,
];
$state = array_merge($state, $request->all());
$this->wepay_payment_driver->payment_hash->data = array_merge((array) $this->wepay_payment_driver->payment_hash->data, $state);
$this->wepay_payment_driver->payment_hash->save();
if(in_array($response->state, ['authorized', 'captured'])){
//success
nlog("success");
$payment_status = $response->state == 'authorized' ? Payment::STATUS_COMPLETED : Payment::STATUS_PENDING;
return $this->processSuccessfulPayment($response, $payment_status, GatewayType::CREDIT_CARD);
}
if(in_array($response->state, ['released', 'cancelled', 'failed', 'expired'])){
//some type of failure
nlog("failure");
$payment_status = $response->state == 'cancelled' ? Payment::STATUS_CANCELLED : Payment::STATUS_FAILED;
$this->processUnSuccessfulPayment($response, $payment_status);
}
}
/*
new The checkout was created by the application. This state typically indicates that checkouts created in WePay's hosted checkout flow are waiting for the payer to submit their information.
authorized The payer entered their payment info and confirmed the payment on WePay. WePay has successfully charged the card.
captured The payment has been reserved from the payer.
released The payment has been credited to the payee account. Note that the released state may be active although there are active partial refunds or partial chargebacks.
cancelled The payment has been cancelled by the payer, payee, or application.
refunded The payment was captured and then refunded by the payer, payee, or application. The payment has been debited from the payee account.
charged back The payment has been charged back by the payer and the payment has been debited from the payee account.
failed The payment has failed.
expired Checkouts expire if they remain in the new state for more than 30 minutes (e.g., they have been abandoned).
*/
/*
https://developer.wepay.com/api/api-calls/checkout
{
"checkout_id": 649945633,
"account_id": 1548718026,
"type": "donation",
"short_description": "test checkout",
"currency": "USD",
"amount": 20,
"state": "authorized",
"soft_descriptor": "WPY*Wolverine",
"auto_release": true,
"create_time": 1463589958,
"gross": 20.88,
"reference_id": null,
"callback_uri": null,
"long_description": null,
"delivery_type": null,
"initiated_by": "merchant",
"in_review": false,
"fee": {
"app_fee": 0,
"processing_fee": 0.88,
"fee_payer": "payer"
},
"chargeback": {
"amount_charged_back": 0,
"dispute_uri": null
},
"refund": {
"amount_refunded": 0,
"refund_reason": null
},
"payment_method": {
"type": "credit_card",
"credit_card": {
"id": 1684847614,
"data": {
"emv_receipt": null,
"signature_url": null
},
"auto_release": false
}
},
"hosted_checkout": null,
"payer": {
"email": "test@example.com",
"name": "Mr Smith",
"home_address": null
},
"npo_information": null,
"payment_error": null
}
*/
private function storePaymentMethod($response, $payment_method_id)
{
nlog("storing card");
$payment_meta = new \stdClass;
$payment_meta->exp_month = (string) $response->expiration_month;
$payment_meta->exp_year = (string) $response->expiration_year;
$payment_meta->brand = (string) $response->credit_card_name;
$payment_meta->last4 = (string) $response->last_four;
$payment_meta->type = GatewayType::CREDIT_CARD;
$data = [
'payment_meta' => $payment_meta,
'token' => $response->credit_card_id,
'payment_method_id' => $payment_method_id,
];
$this->wepay_payment_driver->storeGatewayToken($data);
}
}

View File

@ -0,0 +1,36 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\PaymentDrivers\WePay;
use App\PaymentDrivers\WePayPaymentDriver;
use Illuminate\Http\Request;
class Setup
{
public $wepay;
public function __construct(WePayPaymentDriver $wepay)
{
$this->wepay = $wepay;
}
public function boot($data)
{
/*
'user_id',
'company',
*/
return render('gateways.wepay.signup.index', $data);
}
}

View File

@ -0,0 +1,76 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\PaymentDrivers\WePay;
use App\Exceptions\PaymentFailed;
use App\Jobs\Mail\PaymentFailureMailer;
use App\Jobs\Util\SystemLogger;
use App\Models\PaymentType;
use App\Models\SystemLog;
trait WePayCommon
{
private function processSuccessfulPayment($response, $payment_status, $gateway_type)
{
$data = [
'payment_type' => PaymentType::CREDIT_CARD_OTHER,
'amount' => $response->amount,
'transaction_reference' => $response->checkout_id,
'gateway_type_id' => $gateway_type,
];
$payment = $this->wepay_payment_driver->createPayment($data, $payment_status);
SystemLogger::dispatch(
['response' => $this->wepay_payment_driver->payment_hash->data->server_response, 'data' => $data],
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_SUCCESS,
SystemLog::TYPE_WEPAY,
$this->wepay_payment_driver->client,
$this->wepay_payment_driver->client->company,
);
return redirect()->route('client.payments.show', ['payment' => $this->wepay_payment_driver->encodePrimaryKey($payment->id)]);
}
private function processUnSuccessfulPayment($response, $payment_status)
{
PaymentFailureMailer::dispatch($this->wepay_payment_driver->client, $response->state, $this->wepay_payment_driver->client->company, $response->amount);
PaymentFailureMailer::dispatch(
$this->wepay_payment_driver->client,
$response,
$this->wepay_payment_driver->client->company,
$response->gross
);
$message = [
'server_response' => $response,
'data' => $this->wepay_payment_driver->payment_hash->data,
];
SystemLogger::dispatch(
$message,
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_FAILURE,
SystemLog::TYPE_WEPAY,
$this->wepay_payment_driver->client,
$this->wepay_payment_driver->client->company,
);
throw new PaymentFailed('Failed to process the payment.', 500);
}
}

View File

@ -0,0 +1,357 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\PaymentDrivers;
use App\Http\Requests\Payments\PaymentWebhookRequest;
use App\Models\ClientGatewayToken;
use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentHash;
use App\Models\SystemLog;
use App\PaymentDrivers\WePay\ACH;
use App\PaymentDrivers\WePay\CreditCard;
use App\PaymentDrivers\WePay\Setup;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Request;
use WePay;
class WePayPaymentDriver extends BaseDriver
{
use MakesHash;
/* Does this gateway support refunds? */
public $refundable = true;
/* Does this gateway support token billing? */
public $token_billing = true;
/* Does this gateway support authorizations? */
public $can_authorise_credit_card = true;
/* Initialized gateway */
public $wepay;
/* Initialized payment method */
public $payment_method;
/* Maps the Payment Gateway Type - to its implementation */
public static $methods = [
GatewayType::CREDIT_CARD => CreditCard::class,
GatewayType::BANK_TRANSFER => ACH::class,
];
const SYSTEM_LOG_TYPE = SystemLog::TYPE_WEPAY;
public function init()
{
if (WePay::getEnvironment() == 'none') {
if(config('ninja.wepay.environment') == 'staging')
WePay::useStaging(config('ninja.wepay.client_id'), config('ninja.wepay.client_secret'));
else
WePay::useProduction(config('ninja.wepay.client_id'), config('ninja.wepay.client_secret'));
}
if ($this->company_gateway)
$this->wepay = new WePay($this->company_gateway->getConfigField('accessToken'));
else
$this->wepay = new WePay(null);
return $this;
}
/**
* Return the gateway types that have been enabled
*
* @return array
*/
public function gatewayTypes(): array
{
$types = [];
if($this->company_gateway->fees_and_limits->{GatewayType::BANK_TRANSFER}->is_enabled)
$types[] = GatewayType::CREDIT_CARD;
if($this->company_gateway->fees_and_limits->{GatewayType::BANK_TRANSFER}->is_enabled)
$types[] = GatewayType::BANK_TRANSFER;
return $types;
}
/**
* Setup the gateway
*
* @param array $data user_id + company
* @return view
*/
public function setup(array $data)
{
return (new Setup($this))->boot($data);
}
/**
* Set the payment method
*
* @param int $payment_method_id Alias of GatewayType
*/
public function setPaymentMethod($payment_method_id)
{
$class = self::$methods[$payment_method_id];
$this->payment_method = new $class($this);
return $this;
}
public function authorizeView(array $data)
{
$this->init();
$data['gateway'] = $this->wepay;
$client = $data['client'];
$contact = $client->primary_contact()->first() ? $client->primary_contact()->first() : $lient->contacts->first();
$data['contact'] = $contact;
return $this->payment_method->authorizeView($data); //this is your custom implementation from here
}
public function authorizeResponse($request)
{
$this->init();
return $this->payment_method->authorizeResponse($request); //this is your custom implementation from here
}
public function verificationView(ClientGatewayToken $cgt)
{
$this->init();
return $this->payment_method->verificationView($cgt);
}
public function processVerification(Request $request, ClientGatewayToken $cgt)
{
$this->init();
return $this->payment_method->processVerification($request, $cgt);
}
public function processPaymentView(array $data)
{
$this->init();
return $this->payment_method->paymentView($data); //this is your custom implementation from here
}
public function processPaymentResponse($request)
{
$this->init();
return $this->payment_method->paymentResponse($request); //this is your custom implementation from here
}
public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash)
{
return $this->payment_method->yourTokenBillingImplmentation(); //this is your custom implementation from here
}
public function processWebhookRequest(PaymentWebhookRequest $request, Payment $payment = null)
{
$this->init();
$input = $request->all();
$accountId = $this->company_gateway->getConfigField('accountId');
foreach (array_keys($input) as $key) {
if ('_id' == substr($key, -3)) {
$objectType = substr($key, 0, -3);
$objectId = $input[$key];
break;
}
}
if (! isset($objectType)) {
throw new Exception('Could not find object id parameter');
}
if ($objectType == 'credit_card') {
$payment_method = ClientGatewayToken::where('token', $objectId)->first();
if (! $paymentMethod)
throw new \Exception('Unknown payment method');
$source = $this->wepay->request('credit_card', array(
'client_id' => config('ninja.wepay.client_id'),
'client_secret' => config('ninja.wepay.client_secret'),
'credit_card_id' => (int)$objectId,
));
if ($source->state == 'deleted') {
$payment_method->delete();
} else {
//$this->paymentService->convertPaymentMethodFromWePay($source, null, $paymentMethod)->save();
}
return 'Processed successfully';
} elseif ($objectType == 'account') {
if ($accountId != $objectId) {
throw new \Exception('Unknown account');
}
$wepayAccount = $this->wepay->request('account', array(
'account_id' => (int)$objectId,
));
if ($wepayAccount->state == 'deleted') {
$this->company_gateway->delete();
} else {
$config->state = $wepayAccount->state;
$this->company_gateway->setConfig($config);
$this->company_gateway->save();
}
return ['message' => 'Processed successfully'];
} elseif ($objectType == 'checkout') {
$payment = Payment::where('company_id', $this->company_gateway->company_id)
->where('transaction_reference', '=', $objectId)
->first();
if (! $payment) {
throw new Exception('Unknown payment');
}
if ($payment->is_deleted) {
throw new \Exception('Payment is deleted');
}
$checkout = $this->wepay->request('checkout', array(
'checkout_id' => intval($objectId),
));
if ($checkout->state == 'captured') {
$payment->status_id = Payment::STATUS_COMPLETED;
$payment->save();
} elseif ($checkout->state == 'cancelled') {
$payment->service()->deletePayment()->save();
} elseif ($checkout->state == 'failed') {
$payment->status_id = Payment::STATUS_FAILED;
$payment->save();
}
return 'Processed successfully';
} else {
return 'Ignoring event';
}
return true;
}
public function refund(Payment $payment, $amount, $return_client_response = false)
{
$this->init();
$response = $this->wepay->request('checkout/refund', array(
'checkout_id' => $payment->transaction_reference,
'refund_reason' => 'Refund',
'amount' => $amount
));
return [
'transaction_reference' => $response->checkout_id,
'transaction_response' => json_encode($response),
'success' => $response->state == 'refunded' ? true : false,
'description' => 'refund',
'code' => 0,
];
}
public function detach(ClientGatewayToken $token)
{
/*Bank accounts cannot be deleted - only CC*/
if($token->gateway_type_id == 2)
return true;
$this->init();
$response = $this->wepay->request('/credit_card/delete', [
'client_id' => config('ninja.wepay.client_id'),
'client_secret' => config('ninja.wepay.client_secret'),
'credit_card_id' => intval($token->token),
]);
if ($response->state == 'deleted') {
return true;
} else {
throw new \Exception(trans('texts.failed_remove_payment_method'));
}
}
public function getClientRequiredFields(): array
{
$fields = [
['name' => 'client_postal_code', 'label' => ctrans('texts.postal_code'), 'type' => 'text', 'validation' => 'required'],
['name' => 'contact_email', 'label' => ctrans('texts.email'), 'type' => 'text', 'validation' => 'required'],
];
if ($this->company_gateway->require_client_name) {
$fields[] = ['name' => 'client_name', 'label' => ctrans('texts.client_name'), 'type' => 'text', 'validation' => 'required'];
}
if ($this->company_gateway->require_client_phone) {
$fields[] = ['name' => 'client_phone', 'label' => ctrans('texts.client_phone'), 'type' => 'tel', 'validation' => 'required'];
}
if ($this->company_gateway->require_contact_name) {
$fields[] = ['name' => 'contact_first_name', 'label' => ctrans('texts.first_name'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'contact_last_name', 'label' => ctrans('texts.last_name'), 'type' => 'text', 'validation' => 'required'];
}
if ($this->company_gateway->require_contact_email) {
$fields[] = ['name' => 'contact_email', 'label' => ctrans('texts.email'), 'type' => 'text', 'validation' => 'required,email:rfc'];
}
if ($this->company_gateway->require_billing_address) {
$fields[] = ['name' => 'client_address_line_1', 'label' => ctrans('texts.address1'), 'type' => 'text', 'validation' => 'required'];
// $fields[] = ['name' => 'client_address_line_2', 'label' => ctrans('texts.address2'), 'type' => 'text', 'validation' => 'nullable'];
$fields[] = ['name' => 'client_city', 'label' => ctrans('texts.city'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_state', 'label' => ctrans('texts.state'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_country_id', 'label' => ctrans('texts.country'), 'type' => 'text', 'validation' => 'required'];
}
if ($this->company_gateway->require_shipping_address) {
$fields[] = ['name' => 'client_shipping_address_line_1', 'label' => ctrans('texts.shipping_address1'), 'type' => 'text', 'validation' => 'required'];
// $fields[] = ['name' => 'client_shipping_address_line_2', 'label' => ctrans('texts.shipping_address2'), 'type' => 'text', 'validation' => 'sometimes'];
$fields[] = ['name' => 'client_shipping_city', 'label' => ctrans('texts.shipping_city'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_shipping_state', 'label' => ctrans('texts.shipping_state'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_shipping_postal_code', 'label' => ctrans('texts.shipping_postal_code'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_shipping_country_id', 'label' => ctrans('texts.shipping_country'), 'type' => 'text', 'validation' => 'required'];
}
return $fields;
}
}

View File

@ -330,8 +330,6 @@ class BaseRepository
$model = $model->calc()->getCredit(); $model = $model->calc()->getCredit();
// $model->ledger()->updateCreditBalance(-1*($state['finished_amount'] - $state['starting_amount']));
if (! $model->design_id) if (! $model->design_id)
$model->design_id = $this->decodePrimaryKey($client->getSetting('credit_design_id')); $model->design_id = $this->decodePrimaryKey($client->getSetting('credit_design_id'));
@ -339,12 +337,18 @@ class BaseRepository
if ($model instanceof Quote) { if ($model instanceof Quote) {
if (! $model->design_id)
$model->design_id = $this->decodePrimaryKey($client->getSetting('quote_design_id'));
$model = $model->calc()->getQuote(); $model = $model->calc()->getQuote();
} }
if ($model instanceof RecurringInvoice) { if ($model instanceof RecurringInvoice) {
if (! $model->design_id)
$model->design_id = $this->decodePrimaryKey($client->getSetting('invoice_design_id'));
$model = $model->calc()->getRecurringInvoice(); $model = $model->calc()->getRecurringInvoice();
} }

View File

@ -90,6 +90,7 @@ class PaymentRepository extends BaseRepository {
$client->service()->updatePaidToDate($_credit_totals)->save(); $client->service()->updatePaidToDate($_credit_totals)->save();
} }
} }
} }
/*Fill the payment*/ /*Fill the payment*/
@ -184,6 +185,10 @@ class PaymentRepository extends BaseRepository {
*/ */
private function processExchangeRates($data, $payment) private function processExchangeRates($data, $payment)
{ {
if(array_key_exists('exchange_rate', $data) && isset($data['exchange_rate']))
return $payment;
$client = Client::find($data['client_id']); $client = Client::find($data['client_id']);
$client_currency = $client->getSetting('currency_id'); $client_currency = $client->getSetting('currency_id');

View File

@ -16,12 +16,14 @@ use App\Events\Payment\PaymentWasCreated;
use App\Factory\PaymentFactory; use App\Factory\PaymentFactory;
use App\Jobs\Invoice\InvoiceWorkflowSettings; use App\Jobs\Invoice\InvoiceWorkflowSettings;
use App\Jobs\Payment\EmailPayment; use App\Jobs\Payment\EmailPayment;
use App\Libraries\Currency\Conversion\CurrencyApi;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Payment; use App\Models\Payment;
use App\Services\AbstractService; use App\Services\AbstractService;
use App\Services\Client\ClientService; use App\Services\Client\ClientService;
use App\Utils\Ninja; use App\Utils\Ninja;
use App\Utils\Traits\GeneratesCounter; use App\Utils\Traits\GeneratesCounter;
use Illuminate\Support\Carbon;
class MarkPaid extends AbstractService class MarkPaid extends AbstractService
{ {
@ -63,6 +65,8 @@ class MarkPaid extends AbstractService
/* Create a payment relationship to the invoice entity */ /* Create a payment relationship to the invoice entity */
$payment->save(); $payment->save();
$this->setExchangeRate($payment);
$payment->invoices()->attach($this->invoice->id, [ $payment->invoices()->attach($this->invoice->id, [
'amount' => $payment->amount, 'amount' => $payment->amount,
]); ]);
@ -70,6 +74,7 @@ class MarkPaid extends AbstractService
$this->invoice->next_send_date = null; $this->invoice->next_send_date = null;
$this->invoice->service() $this->invoice->service()
->setExchangeRate()
->updateBalance($payment->amount * -1) ->updateBalance($payment->amount * -1)
->updatePaidToDate($payment->amount) ->updatePaidToDate($payment->amount)
->setStatus(Invoice::STATUS_PAID) ->setStatus(Invoice::STATUS_PAID)
@ -96,4 +101,22 @@ class MarkPaid extends AbstractService
return $this->invoice; return $this->invoice;
} }
private function setExchangeRate(Payment $payment)
{
$client_currency = $payment->client->getSetting('currency_id');
$company_currency = $payment->client->company->settings->currency_id;
if ($company_currency != $client_currency) {
$exchange_rate = new CurrencyApi();
$payment->exchange_rate = $exchange_rate->exchangeRate($client_currency, $company_currency, Carbon::parse($payment->date));
$payment->exchange_currency_id = $client_currency;
$payment->save();
}
}
} }

View File

@ -37,7 +37,7 @@ class UpdateInvoicePayment
{ {
$paid_invoices = $this->payment_hash->invoices(); $paid_invoices = $this->payment_hash->invoices();
$invoices = Invoice::whereIn('id', $this->transformKeys(array_column($paid_invoices, 'invoice_id')))->get(); $invoices = Invoice::whereIn('id', $this->transformKeys(array_column($paid_invoices, 'invoice_id')))->withTrashed()->get();
collect($paid_invoices)->each(function ($paid_invoice) use ($invoices) { collect($paid_invoices)->each(function ($paid_invoice) use ($invoices) {

View File

@ -15,6 +15,7 @@ use App\Factory\ClientContactFactory;
use App\Factory\QuoteInvitationFactory; use App\Factory\QuoteInvitationFactory;
use App\Models\Quote; use App\Models\Quote;
use App\Models\QuoteInvitation; use App\Models\QuoteInvitation;
use Illuminate\Support\Str;
class CreateInvitations class CreateInvitations
{ {

View File

@ -629,7 +629,7 @@ class SubscriptionService
} }
$client = \App\Models\Client::find($this->decodePrimaryKey($body['client'])); $client = Client::where('id', $this->decodePrimaryKey($body['client']))->withTrashed()->first();
SystemLogger::dispatch( SystemLogger::dispatch(
$body, $body,
@ -639,6 +639,7 @@ class SubscriptionService
$client, $client,
$client->company, $client->company,
); );
if(is_array($body)) if(is_array($body))
return $response; return $response;

View File

@ -70,27 +70,27 @@ class Statics
$data = []; $data = [];
foreach (config('ninja.cached_tables') as $name => $class) { foreach (config('ninja.cached_tables') as $name => $class) {
if (!Cache::has($name)) {
// if (!Cache::has($name)) { // check that the table exists in case the migration is pending
if (!Schema::hasTable((new $class())->getTable())) {
// // check that the table exists in case the migration is pending continue;
// if (!Schema::hasTable((new $class())->getTable())) { }
// continue; if ($name == 'payment_terms') {
// } $orderBy = 'num_days';
// if ($name == 'payment_terms') { } elseif ($name == 'fonts') {
// $orderBy = 'num_days'; $orderBy = 'sort_order';
// } elseif ($name == 'fonts') { } elseif (in_array($name, ['currencies', 'industries', 'languages', 'countries', 'banks'])) {
// $orderBy = 'sort_order'; $orderBy = 'name';
// } elseif (in_array($name, ['currencies', 'industries', 'languages', 'countries', 'banks'])) { } else {
// $orderBy = 'name'; $orderBy = 'id';
// } else { }
// $orderBy = 'id'; $tableData = $class::orderBy($orderBy)->get();
// } if ($tableData->count()) {
// $tableData = $class::orderBy($orderBy)->get(); Cache::forever($name, $tableData);
// if ($tableData->count()) { }
// Cache::forever($name, $tableData); }
// }
// }
$data[$name] = Cache::get($name); $data[$name] = Cache::get($name);
} }

View File

@ -72,6 +72,7 @@
"turbo124/beacon": "^1.0", "turbo124/beacon": "^1.0",
"turbo124/laravel-gmail": "^5", "turbo124/laravel-gmail": "^5",
"webpatser/laravel-countries": "dev-master#75992ad", "webpatser/laravel-countries": "dev-master#75992ad",
"wepay/php-sdk": "^0.3",
"wildbit/swiftmailer-postmark": "^3.3" "wildbit/swiftmailer-postmark": "^3.3"
}, },
"require-dev": { "require-dev": {

369
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "551d077c3d25c2a962f0c2c270618582", "content-hash": "013b0357f14c1782315168bc42234b34",
"packages": [ "packages": [
{ {
"name": "asm/php-ansible", "name": "asm/php-ansible",
@ -159,16 +159,16 @@
}, },
{ {
"name": "aws/aws-sdk-php", "name": "aws/aws-sdk-php",
"version": "3.183.10", "version": "3.184.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/aws/aws-sdk-php.git", "url": "https://github.com/aws/aws-sdk-php.git",
"reference": "3995354f4791f8ca85f5208325cef9065e471f3b" "reference": "78fe691ab466fecf195209672f6c00c5d4ed219a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/3995354f4791f8ca85f5208325cef9065e471f3b", "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/78fe691ab466fecf195209672f6c00c5d4ed219a",
"reference": "3995354f4791f8ca85f5208325cef9065e471f3b", "reference": "78fe691ab466fecf195209672f6c00c5d4ed219a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -243,9 +243,9 @@
"support": { "support": {
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
"issues": "https://github.com/aws/aws-sdk-php/issues", "issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.183.10" "source": "https://github.com/aws/aws-sdk-php/tree/3.184.2"
}, },
"time": "2021-06-01T18:13:35+00:00" "time": "2021-06-11T18:20:15+00:00"
}, },
{ {
"name": "bacon/bacon-qr-code", "name": "bacon/bacon-qr-code",
@ -460,16 +460,16 @@
}, },
{ {
"name": "checkout/checkout-sdk-php", "name": "checkout/checkout-sdk-php",
"version": "1.0.15", "version": "1.0.16",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/checkout/checkout-sdk-php.git", "url": "https://github.com/checkout/checkout-sdk-php.git",
"reference": "f73f6478c966968f2f0b9a9525c4bfb9b8e046f1" "reference": "81c6aa884fb586b8a9456aecf83b639fed205f86"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/checkout/checkout-sdk-php/zipball/f73f6478c966968f2f0b9a9525c4bfb9b8e046f1", "url": "https://api.github.com/repos/checkout/checkout-sdk-php/zipball/81c6aa884fb586b8a9456aecf83b639fed205f86",
"reference": "f73f6478c966968f2f0b9a9525c4bfb9b8e046f1", "reference": "81c6aa884fb586b8a9456aecf83b639fed205f86",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -513,9 +513,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/checkout/checkout-sdk-php/issues", "issues": "https://github.com/checkout/checkout-sdk-php/issues",
"source": "https://github.com/checkout/checkout-sdk-php/tree/1.0.15" "source": "https://github.com/checkout/checkout-sdk-php/tree/1.0.16"
}, },
"time": "2021-05-25T07:59:04+00:00" "time": "2021-06-03T13:52:46+00:00"
}, },
{ {
"name": "cleverit/ubl_invoice", "name": "cleverit/ubl_invoice",
@ -804,16 +804,16 @@
}, },
{ {
"name": "composer/ca-bundle", "name": "composer/ca-bundle",
"version": "1.2.9", "version": "1.2.10",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/composer/ca-bundle.git", "url": "https://github.com/composer/ca-bundle.git",
"reference": "78a0e288fdcebf92aa2318a8d3656168da6ac1a5" "reference": "9fdb22c2e97a614657716178093cd1da90a64aa8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/78a0e288fdcebf92aa2318a8d3656168da6ac1a5", "url": "https://api.github.com/repos/composer/ca-bundle/zipball/9fdb22c2e97a614657716178093cd1da90a64aa8",
"reference": "78a0e288fdcebf92aa2318a8d3656168da6ac1a5", "reference": "9fdb22c2e97a614657716178093cd1da90a64aa8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -860,7 +860,7 @@
"support": { "support": {
"irc": "irc://irc.freenode.org/composer", "irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/ca-bundle/issues", "issues": "https://github.com/composer/ca-bundle/issues",
"source": "https://github.com/composer/ca-bundle/tree/1.2.9" "source": "https://github.com/composer/ca-bundle/tree/1.2.10"
}, },
"funding": [ "funding": [
{ {
@ -876,20 +876,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-01-12T12:10:35+00:00" "time": "2021-06-07T13:58:28+00:00"
}, },
{ {
"name": "composer/composer", "name": "composer/composer",
"version": "2.0.14", "version": "2.1.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/composer/composer.git", "url": "https://github.com/composer/composer.git",
"reference": "92b2ccbef65292ba9f2004271ef47c7231e2eed5" "reference": "fc5c4573aafce3a018eb7f1f8f91cea423970f2e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/composer/composer/zipball/92b2ccbef65292ba9f2004271ef47c7231e2eed5", "url": "https://api.github.com/repos/composer/composer/zipball/fc5c4573aafce3a018eb7f1f8f91cea423970f2e",
"reference": "92b2ccbef65292ba9f2004271ef47c7231e2eed5", "reference": "fc5c4573aafce3a018eb7f1f8f91cea423970f2e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -924,7 +924,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "2.0-dev" "dev-master": "2.1-dev"
} }
}, },
"autoload": { "autoload": {
@ -958,7 +958,7 @@
"support": { "support": {
"irc": "irc://irc.freenode.org/composer", "irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/composer/issues", "issues": "https://github.com/composer/composer/issues",
"source": "https://github.com/composer/composer/tree/2.0.14" "source": "https://github.com/composer/composer/tree/2.1.3"
}, },
"funding": [ "funding": [
{ {
@ -974,7 +974,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-05-21T15:03:37+00:00" "time": "2021-06-09T14:31:20+00:00"
}, },
{ {
"name": "composer/metadata-minifier", "name": "composer/metadata-minifier",
@ -2219,16 +2219,16 @@
}, },
{ {
"name": "google/apiclient", "name": "google/apiclient",
"version": "v2.9.1", "version": "v2.9.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/googleapis/google-api-php-client.git", "url": "https://github.com/googleapis/google-api-php-client.git",
"reference": "2fb6e702aca5d68203fa737f89f6f774022494c6" "reference": "e9ef4c26a044b8d39a46bcf296be795fe24a1849"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/2fb6e702aca5d68203fa737f89f6f774022494c6", "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/e9ef4c26a044b8d39a46bcf296be795fe24a1849",
"reference": "2fb6e702aca5d68203fa737f89f6f774022494c6", "reference": "e9ef4c26a044b8d39a46bcf296be795fe24a1849",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2243,7 +2243,7 @@
}, },
"require-dev": { "require-dev": {
"cache/filesystem-adapter": "^0.3.2|^1.1", "cache/filesystem-adapter": "^0.3.2|^1.1",
"composer/composer": "^1.10", "composer/composer": "^1.10.22",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7", "dealerdirect/phpcodesniffer-composer-installer": "^0.7",
"phpcompatibility/php-compatibility": "^9.2", "phpcompatibility/php-compatibility": "^9.2",
"phpunit/phpunit": "^5.7||^8.5.13", "phpunit/phpunit": "^5.7||^8.5.13",
@ -2282,29 +2282,29 @@
], ],
"support": { "support": {
"issues": "https://github.com/googleapis/google-api-php-client/issues", "issues": "https://github.com/googleapis/google-api-php-client/issues",
"source": "https://github.com/googleapis/google-api-php-client/tree/v2.9.1" "source": "https://github.com/googleapis/google-api-php-client/tree/v2.9.2"
}, },
"time": "2021-01-19T17:48:59+00:00" "time": "2021-06-09T22:15:08+00:00"
}, },
{ {
"name": "google/apiclient-services", "name": "google/apiclient-services",
"version": "v0.177.0", "version": "v0.181.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/googleapis/google-api-php-client-services.git", "url": "https://github.com/googleapis/google-api-php-client-services.git",
"reference": "316cbf9b02c575a140d8cbeca48a3ca0070fcd5a" "reference": "a4ea5fd96887d654d10d446b239e1ff60240e2c1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/316cbf9b02c575a140d8cbeca48a3ca0070fcd5a", "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/a4ea5fd96887d654d10d446b239e1ff60240e2c1",
"reference": "316cbf9b02c575a140d8cbeca48a3ca0070fcd5a", "reference": "a4ea5fd96887d654d10d446b239e1ff60240e2c1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.4" "php": ">=5.6"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^4.8|^5" "phpunit/phpunit": "^5.7||^8.5.13"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@ -2323,9 +2323,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/googleapis/google-api-php-client-services/issues", "issues": "https://github.com/googleapis/google-api-php-client-services/issues",
"source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.177.0" "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.181.0"
}, },
"time": "2021-05-15T11:18:02+00:00" "time": "2021-06-13T11:20:02+00:00"
}, },
{ {
"name": "google/auth", "name": "google/auth",
@ -3062,16 +3062,16 @@
}, },
{ {
"name": "laravel/framework", "name": "laravel/framework",
"version": "v8.44.0", "version": "v8.46.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/framework.git", "url": "https://github.com/laravel/framework.git",
"reference": "7b3b27dc8911ab02a69731af2ba97b5130b2ddb8" "reference": "a18266c612e0e6aba5e0174b3c873d2d217dccfb"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/7b3b27dc8911ab02a69731af2ba97b5130b2ddb8", "url": "https://api.github.com/repos/laravel/framework/zipball/a18266c612e0e6aba5e0174b3c873d2d217dccfb",
"reference": "7b3b27dc8911ab02a69731af2ba97b5130b2ddb8", "reference": "a18266c612e0e6aba5e0174b3c873d2d217dccfb",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3153,7 +3153,7 @@
"orchestra/testbench-core": "^6.8", "orchestra/testbench-core": "^6.8",
"pda/pheanstalk": "^4.0", "pda/pheanstalk": "^4.0",
"phpunit/phpunit": "^8.5.8|^9.3.3", "phpunit/phpunit": "^8.5.8|^9.3.3",
"predis/predis": "^1.1.1", "predis/predis": "^1.1.2",
"symfony/cache": "^5.1.4" "symfony/cache": "^5.1.4"
}, },
"suggest": { "suggest": {
@ -3226,7 +3226,7 @@
"issues": "https://github.com/laravel/framework/issues", "issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework" "source": "https://github.com/laravel/framework"
}, },
"time": "2021-05-27T16:46:06+00:00" "time": "2021-06-08T13:36:46+00:00"
}, },
{ {
"name": "laravel/slack-notification-channel", "name": "laravel/slack-notification-channel",
@ -4067,23 +4067,23 @@
}, },
{ {
"name": "league/omnipay", "name": "league/omnipay",
"version": "v3.2.0", "version": "v3.2.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/thephpleague/omnipay.git", "url": "https://github.com/thephpleague/omnipay.git",
"reference": "0caded2a46f809dc42e350e07e798cc3c45cd47f" "reference": "38f66a0cc043ed51d6edf7956d6439a2f263501f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/thephpleague/omnipay/zipball/0caded2a46f809dc42e350e07e798cc3c45cd47f", "url": "https://api.github.com/repos/thephpleague/omnipay/zipball/38f66a0cc043ed51d6edf7956d6439a2f263501f",
"reference": "0caded2a46f809dc42e350e07e798cc3c45cd47f", "reference": "38f66a0cc043ed51d6edf7956d6439a2f263501f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"omnipay/common": "^3.1", "omnipay/common": "^3.1",
"php": "^7.3|^8.0", "php": "^7.2|^8.0",
"php-http/discovery": "^1.12", "php-http/discovery": "^1.14",
"php-http/guzzle7-adapter": "^0.1" "php-http/guzzle7-adapter": "^1"
}, },
"require-dev": { "require-dev": {
"omnipay/tests": "^3|^4" "omnipay/tests": "^3|^4"
@ -4118,7 +4118,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/thephpleague/omnipay/issues", "issues": "https://github.com/thephpleague/omnipay/issues",
"source": "https://github.com/thephpleague/omnipay/tree/v3.2.0" "source": "https://github.com/thephpleague/omnipay/tree/v3.2.1"
}, },
"funding": [ "funding": [
{ {
@ -4126,7 +4126,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2021-06-01T09:16:20+00:00" "time": "2021-06-05T11:34:12+00:00"
}, },
{ {
"name": "livewire/livewire", "name": "livewire/livewire",
@ -4570,16 +4570,16 @@
}, },
{ {
"name": "nesbot/carbon", "name": "nesbot/carbon",
"version": "2.48.1", "version": "2.49.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/briannesbitt/Carbon.git", "url": "https://github.com/briannesbitt/Carbon.git",
"reference": "8d1f50f1436fb4b05e7127360483dd9c6e73da16" "reference": "93d9db91c0235c486875d22f1e08b50bdf3e6eee"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/8d1f50f1436fb4b05e7127360483dd9c6e73da16", "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/93d9db91c0235c486875d22f1e08b50bdf3e6eee",
"reference": "8d1f50f1436fb4b05e7127360483dd9c6e73da16", "reference": "93d9db91c0235c486875d22f1e08b50bdf3e6eee",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4659,7 +4659,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-05-26T22:08:38+00:00" "time": "2021-06-02T07:31:40+00:00"
}, },
{ {
"name": "nikic/php-parser", "name": "nikic/php-parser",
@ -4877,29 +4877,29 @@
}, },
{ {
"name": "omnipay/common", "name": "omnipay/common",
"version": "v3.1.0", "version": "v3.1.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/thephpleague/omnipay-common.git", "url": "https://github.com/thephpleague/omnipay-common.git",
"reference": "fae2bc97a1b6c808361c5cafc796d380130714c7" "reference": "5b16387ec5ab1b9ff86bdf0f20415088693b9948"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/thephpleague/omnipay-common/zipball/fae2bc97a1b6c808361c5cafc796d380130714c7", "url": "https://api.github.com/repos/thephpleague/omnipay-common/zipball/5b16387ec5ab1b9ff86bdf0f20415088693b9948",
"reference": "fae2bc97a1b6c808361c5cafc796d380130714c7", "reference": "5b16387ec5ab1b9ff86bdf0f20415088693b9948",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"moneyphp/money": "^3.1", "moneyphp/money": "^3.1",
"php": "^7.3|^8", "php": "^7.2|^8",
"php-http/client-implementation": "^1", "php-http/client-implementation": "^1",
"php-http/discovery": "^1.13", "php-http/discovery": "^1.14",
"php-http/guzzle7-adapter": "^0.1",
"php-http/message": "^1.5", "php-http/message": "^1.5",
"symfony/http-foundation": "^2.1|^3|^4|^5" "symfony/http-foundation": "^2.1|^3|^4|^5"
}, },
"require-dev": { "require-dev": {
"omnipay/tests": "^4", "omnipay/tests": "^4.1",
"php-http/guzzle7-adapter": "^1",
"php-http/mock-client": "^1", "php-http/mock-client": "^1",
"squizlabs/php_codesniffer": "^3.5" "squizlabs/php_codesniffer": "^3.5"
}, },
@ -4909,7 +4909,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "3.0.x-dev" "dev-master": "3.1.x-dev"
} }
}, },
"autoload": { "autoload": {
@ -4957,7 +4957,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/thephpleague/omnipay-common/issues", "issues": "https://github.com/thephpleague/omnipay-common/issues",
"source": "https://github.com/thephpleague/omnipay-common/tree/v3.1.0" "source": "https://github.com/thephpleague/omnipay-common/tree/v3.1.2"
}, },
"funding": [ "funding": [
{ {
@ -4965,7 +4965,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2021-06-01T08:17:22+00:00" "time": "2021-06-05T11:36:12+00:00"
}, },
{ {
"name": "omnipay/paypal", "name": "omnipay/paypal",
@ -5358,16 +5358,16 @@
}, },
{ {
"name": "php-http/guzzle7-adapter", "name": "php-http/guzzle7-adapter",
"version": "0.1.1", "version": "1.0.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/php-http/guzzle7-adapter.git", "url": "https://github.com/php-http/guzzle7-adapter.git",
"reference": "1967de656b9679a2a6a66d0e4e16fa99bbed1ad1" "reference": "fb075a71dbfa4847cf0c2938c4e5a9c478ef8b01"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/php-http/guzzle7-adapter/zipball/1967de656b9679a2a6a66d0e4e16fa99bbed1ad1", "url": "https://api.github.com/repos/php-http/guzzle7-adapter/zipball/fb075a71dbfa4847cf0c2938c4e5a9c478ef8b01",
"reference": "1967de656b9679a2a6a66d0e4e16fa99bbed1ad1", "reference": "fb075a71dbfa4847cf0c2938c4e5a9c478ef8b01",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5414,9 +5414,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/php-http/guzzle7-adapter/issues", "issues": "https://github.com/php-http/guzzle7-adapter/issues",
"source": "https://github.com/php-http/guzzle7-adapter/tree/0.1.1" "source": "https://github.com/php-http/guzzle7-adapter/tree/1.0.0"
}, },
"time": "2020-10-21T17:30:51+00:00" "time": "2021-03-09T07:35:15+00:00"
}, },
{ {
"name": "php-http/httplug", "name": "php-http/httplug",
@ -5736,16 +5736,16 @@
}, },
{ {
"name": "phpseclib/phpseclib", "name": "phpseclib/phpseclib",
"version": "3.0.8", "version": "3.0.9",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpseclib/phpseclib.git", "url": "https://github.com/phpseclib/phpseclib.git",
"reference": "d9615a6fb970d9933866ca8b4036ec3407b020b6" "reference": "a127a5133804ff2f47ae629dd529b129da616ad7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d9615a6fb970d9933866ca8b4036ec3407b020b6", "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/a127a5133804ff2f47ae629dd529b129da616ad7",
"reference": "d9615a6fb970d9933866ca8b4036ec3407b020b6", "reference": "a127a5133804ff2f47ae629dd529b129da616ad7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5827,7 +5827,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/phpseclib/phpseclib/issues", "issues": "https://github.com/phpseclib/phpseclib/issues",
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.8" "source": "https://github.com/phpseclib/phpseclib/tree/3.0.9"
}, },
"funding": [ "funding": [
{ {
@ -5843,7 +5843,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-04-19T03:20:48+00:00" "time": "2021-06-14T06:54:45+00:00"
}, },
{ {
"name": "pragmarx/google2fa", "name": "pragmarx/google2fa",
@ -7198,16 +7198,16 @@
}, },
{ {
"name": "stripe/stripe-php", "name": "stripe/stripe-php",
"version": "v7.80.0", "version": "v7.83.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/stripe/stripe-php.git", "url": "https://github.com/stripe/stripe-php.git",
"reference": "566900968407302f88a925ba731c87c05fe98a7a" "reference": "bb7244c7334ad8bf30d31bb4972d5aff57df1563"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/stripe/stripe-php/zipball/566900968407302f88a925ba731c87c05fe98a7a", "url": "https://api.github.com/repos/stripe/stripe-php/zipball/bb7244c7334ad8bf30d31bb4972d5aff57df1563",
"reference": "566900968407302f88a925ba731c87c05fe98a7a", "reference": "bb7244c7334ad8bf30d31bb4972d5aff57df1563",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -7253,9 +7253,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/stripe/stripe-php/issues", "issues": "https://github.com/stripe/stripe-php/issues",
"source": "https://github.com/stripe/stripe-php/tree/v7.80.0" "source": "https://github.com/stripe/stripe-php/tree/v7.83.0"
}, },
"time": "2021-05-26T19:10:43+00:00" "time": "2021-06-07T23:15:45+00:00"
}, },
{ {
"name": "swiftmailer/swiftmailer", "name": "swiftmailer/swiftmailer",
@ -8085,16 +8085,16 @@
}, },
{ {
"name": "symfony/http-foundation", "name": "symfony/http-foundation",
"version": "v5.3.0", "version": "v5.3.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-foundation.git", "url": "https://github.com/symfony/http-foundation.git",
"reference": "31f25d99b329a1461f42bcef8505b54926a30be6" "reference": "8827b90cf8806e467124ad476acd15216c2fceb6"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/31f25d99b329a1461f42bcef8505b54926a30be6", "url": "https://api.github.com/repos/symfony/http-foundation/zipball/8827b90cf8806e467124ad476acd15216c2fceb6",
"reference": "31f25d99b329a1461f42bcef8505b54926a30be6", "reference": "8827b90cf8806e467124ad476acd15216c2fceb6",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -8138,7 +8138,7 @@
"description": "Defines an object-oriented layer for the HTTP specification", "description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/http-foundation/tree/v5.3.0" "source": "https://github.com/symfony/http-foundation/tree/v5.3.1"
}, },
"funding": [ "funding": [
{ {
@ -8154,20 +8154,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-05-26T17:43:10+00:00" "time": "2021-06-02T09:32:00+00:00"
}, },
{ {
"name": "symfony/http-kernel", "name": "symfony/http-kernel",
"version": "v5.3.0", "version": "v5.3.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-kernel.git", "url": "https://github.com/symfony/http-kernel.git",
"reference": "f8e8f5391b6909e2f0ba8c12220ab7af3050eb4f" "reference": "74eb022e3bac36b3d3a897951a98759f2b32b864"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/f8e8f5391b6909e2f0ba8c12220ab7af3050eb4f", "url": "https://api.github.com/repos/symfony/http-kernel/zipball/74eb022e3bac36b3d3a897951a98759f2b32b864",
"reference": "f8e8f5391b6909e2f0ba8c12220ab7af3050eb4f", "reference": "74eb022e3bac36b3d3a897951a98759f2b32b864",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -8250,7 +8250,7 @@
"description": "Provides a structured process for converting a Request into a Response", "description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/http-kernel/tree/v5.3.0" "source": "https://github.com/symfony/http-kernel/tree/v5.3.1"
}, },
"funding": [ "funding": [
{ {
@ -8266,7 +8266,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-05-31T10:44:03+00:00" "time": "2021-06-02T10:07:12+00:00"
}, },
{ {
"name": "symfony/mime", "name": "symfony/mime",
@ -10355,6 +10355,57 @@
}, },
"time": "2019-07-12T14:06:05+00:00" "time": "2019-07-12T14:06:05+00:00"
}, },
{
"name": "wepay/php-sdk",
"version": "0.3.1",
"source": {
"type": "git",
"url": "https://github.com/wepay/PHP-SDK.git",
"reference": "2a89ceb2954d117d082f869d3bfcb7864e6c2a7d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/wepay/PHP-SDK/zipball/2a89ceb2954d117d082f869d3bfcb7864e6c2a7d",
"reference": "2a89ceb2954d117d082f869d3bfcb7864e6c2a7d",
"shasum": ""
},
"require": {
"ext-curl": "*",
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "0.2.x-dev"
}
},
"autoload": {
"classmap": [
"wepay.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "WePay",
"email": "api@wepay.com"
}
],
"description": "WePay APIv2 SDK for PHP",
"keywords": [
"payment",
"sdk",
"wepay"
],
"support": {
"issues": "https://github.com/wepay/PHP-SDK/issues",
"source": "https://github.com/wepay/PHP-SDK/tree/master"
},
"time": "2017-01-21T07:03:26+00:00"
},
{ {
"name": "wildbit/swiftmailer-postmark", "name": "wildbit/swiftmailer-postmark",
"version": "3.3.0", "version": "3.3.0",
@ -10693,16 +10744,16 @@
}, },
{ {
"name": "barryvdh/laravel-debugbar", "name": "barryvdh/laravel-debugbar",
"version": "v3.6.0", "version": "v3.6.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/barryvdh/laravel-debugbar.git", "url": "https://github.com/barryvdh/laravel-debugbar.git",
"reference": "bc99f4c52aec0636ecb3aae4576ce84c5773bae2" "reference": "f6f0f895a33cac801286a74355d146bb5384a5da"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/bc99f4c52aec0636ecb3aae4576ce84c5773bae2", "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/f6f0f895a33cac801286a74355d146bb5384a5da",
"reference": "bc99f4c52aec0636ecb3aae4576ce84c5773bae2", "reference": "f6f0f895a33cac801286a74355d146bb5384a5da",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -10762,7 +10813,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/barryvdh/laravel-debugbar/issues", "issues": "https://github.com/barryvdh/laravel-debugbar/issues",
"source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.6.0" "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.6.1"
}, },
"funding": [ "funding": [
{ {
@ -10770,7 +10821,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2021-06-01T08:46:17+00:00" "time": "2021-06-02T06:42:22+00:00"
}, },
{ {
"name": "brianium/paratest", "name": "brianium/paratest",
@ -11263,16 +11314,16 @@
}, },
{ {
"name": "facade/ignition", "name": "facade/ignition",
"version": "2.9.0", "version": "2.10.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/facade/ignition.git", "url": "https://github.com/facade/ignition.git",
"reference": "e7db3b601ce742568b92648818ef903904d20164" "reference": "43688227bbf27c43bc1ad83af224f135b6ef0ff4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/facade/ignition/zipball/e7db3b601ce742568b92648818ef903904d20164", "url": "https://api.github.com/repos/facade/ignition/zipball/43688227bbf27c43bc1ad83af224f135b6ef0ff4",
"reference": "e7db3b601ce742568b92648818ef903904d20164", "reference": "43688227bbf27c43bc1ad83af224f135b6ef0ff4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -11336,7 +11387,7 @@
"issues": "https://github.com/facade/ignition/issues", "issues": "https://github.com/facade/ignition/issues",
"source": "https://github.com/facade/ignition" "source": "https://github.com/facade/ignition"
}, },
"time": "2021-05-05T06:45:12+00:00" "time": "2021-06-11T06:57:25+00:00"
}, },
{ {
"name": "facade/ignition-contracts", "name": "facade/ignition-contracts",
@ -11393,20 +11444,20 @@
}, },
{ {
"name": "felixfbecker/advanced-json-rpc", "name": "felixfbecker/advanced-json-rpc",
"version": "v3.2.0", "version": "v3.2.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git",
"reference": "06f0b06043c7438959dbdeed8bb3f699a19be22e" "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/06f0b06043c7438959dbdeed8bb3f699a19be22e", "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447",
"reference": "06f0b06043c7438959dbdeed8bb3f699a19be22e", "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"netresearch/jsonmapper": "^1.0 || ^2.0", "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0",
"php": "^7.1 || ^8.0", "php": "^7.1 || ^8.0",
"phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0"
}, },
@ -11432,9 +11483,9 @@
"description": "A more advanced JSONRPC implementation", "description": "A more advanced JSONRPC implementation",
"support": { "support": {
"issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues",
"source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.0" "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1"
}, },
"time": "2021-01-10T17:48:47+00:00" "time": "2021-06-11T22:34:44+00:00"
}, },
{ {
"name": "felixfbecker/language-server-protocol", "name": "felixfbecker/language-server-protocol",
@ -11494,16 +11545,16 @@
}, },
{ {
"name": "filp/whoops", "name": "filp/whoops",
"version": "2.12.1", "version": "2.13.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/filp/whoops.git", "url": "https://github.com/filp/whoops.git",
"reference": "c13c0be93cff50f88bbd70827d993026821914dd" "reference": "2edbc73a4687d9085c8f20f398eebade844e8424"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/filp/whoops/zipball/c13c0be93cff50f88bbd70827d993026821914dd", "url": "https://api.github.com/repos/filp/whoops/zipball/2edbc73a4687d9085c8f20f398eebade844e8424",
"reference": "c13c0be93cff50f88bbd70827d993026821914dd", "reference": "2edbc73a4687d9085c8f20f398eebade844e8424",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -11553,7 +11604,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/filp/whoops/issues", "issues": "https://github.com/filp/whoops/issues",
"source": "https://github.com/filp/whoops/tree/2.12.1" "source": "https://github.com/filp/whoops/tree/2.13.0"
}, },
"funding": [ "funding": [
{ {
@ -11561,7 +11612,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2021-04-25T12:00:00+00:00" "time": "2021-06-04T12:00:00+00:00"
}, },
{ {
"name": "friendsofphp/php-cs-fixer", "name": "friendsofphp/php-cs-fixer",
@ -11920,16 +11971,16 @@
}, },
{ {
"name": "netresearch/jsonmapper", "name": "netresearch/jsonmapper",
"version": "v2.1.0", "version": "v4.0.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/cweiske/jsonmapper.git", "url": "https://github.com/cweiske/jsonmapper.git",
"reference": "e0f1e33a71587aca81be5cffbb9746510e1fe04e" "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/e0f1e33a71587aca81be5cffbb9746510e1fe04e", "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d",
"reference": "e0f1e33a71587aca81be5cffbb9746510e1fe04e", "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -11937,10 +11988,10 @@
"ext-pcre": "*", "ext-pcre": "*",
"ext-reflection": "*", "ext-reflection": "*",
"ext-spl": "*", "ext-spl": "*",
"php": ">=5.6" "php": ">=7.1"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "~4.8.35 || ~5.7 || ~6.4 || ~7.0", "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0",
"squizlabs/php_codesniffer": "~3.5" "squizlabs/php_codesniffer": "~3.5"
}, },
"type": "library", "type": "library",
@ -11965,9 +12016,9 @@
"support": { "support": {
"email": "cweiske@cweiske.de", "email": "cweiske@cweiske.de",
"issues": "https://github.com/cweiske/jsonmapper/issues", "issues": "https://github.com/cweiske/jsonmapper/issues",
"source": "https://github.com/cweiske/jsonmapper/tree/master" "source": "https://github.com/cweiske/jsonmapper/tree/v4.0.0"
}, },
"time": "2020-04-16T18:48:43+00:00" "time": "2020-12-01T19:48:11+00:00"
}, },
{ {
"name": "nunomaduro/collision", "name": "nunomaduro/collision",
@ -12821,16 +12872,16 @@
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "9.5.4", "version": "9.5.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "c73c6737305e779771147af66c96ca6a7ed8a741" "reference": "89ff45ea9d70e35522fb6654a2ebc221158de276"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c73c6737305e779771147af66c96ca6a7ed8a741", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/89ff45ea9d70e35522fb6654a2ebc221158de276",
"reference": "c73c6737305e779771147af66c96ca6a7ed8a741", "reference": "89ff45ea9d70e35522fb6654a2ebc221158de276",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -12860,7 +12911,7 @@
"sebastian/global-state": "^5.0.1", "sebastian/global-state": "^5.0.1",
"sebastian/object-enumerator": "^4.0.3", "sebastian/object-enumerator": "^4.0.3",
"sebastian/resource-operations": "^3.0.3", "sebastian/resource-operations": "^3.0.3",
"sebastian/type": "^2.3", "sebastian/type": "^2.3.2",
"sebastian/version": "^3.0.2" "sebastian/version": "^3.0.2"
}, },
"require-dev": { "require-dev": {
@ -12908,7 +12959,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues", "issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.4" "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.5"
}, },
"funding": [ "funding": [
{ {
@ -12920,7 +12971,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2021-03-23T07:16:29+00:00" "time": "2021-06-05T04:49:07+00:00"
}, },
{ {
"name": "sebastian/cli-parser", "name": "sebastian/cli-parser",
@ -13428,16 +13479,16 @@
}, },
{ {
"name": "sebastian/global-state", "name": "sebastian/global-state",
"version": "5.0.2", "version": "5.0.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git", "url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "a90ccbddffa067b51f574dea6eb25d5680839455" "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/a90ccbddffa067b51f574dea6eb25d5680839455", "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/23bd5951f7ff26f12d4e3242864df3e08dec4e49",
"reference": "a90ccbddffa067b51f574dea6eb25d5680839455", "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -13480,7 +13531,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues", "issues": "https://github.com/sebastianbergmann/global-state/issues",
"source": "https://github.com/sebastianbergmann/global-state/tree/5.0.2" "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.3"
}, },
"funding": [ "funding": [
{ {
@ -13488,7 +13539,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-26T15:55:19+00:00" "time": "2021-06-11T13:31:12+00:00"
}, },
{ {
"name": "sebastian/lines-of-code", "name": "sebastian/lines-of-code",
@ -13779,16 +13830,16 @@
}, },
{ {
"name": "sebastian/type", "name": "sebastian/type",
"version": "2.3.1", "version": "2.3.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/type.git", "url": "https://github.com/sebastianbergmann/type.git",
"reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2" "reference": "0d1c587401514d17e8f9258a27e23527cb1b06c1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/81cd61ab7bbf2de744aba0ea61fae32f721df3d2", "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/0d1c587401514d17e8f9258a27e23527cb1b06c1",
"reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2", "reference": "0d1c587401514d17e8f9258a27e23527cb1b06c1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -13823,7 +13874,7 @@
"homepage": "https://github.com/sebastianbergmann/type", "homepage": "https://github.com/sebastianbergmann/type",
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/type/issues", "issues": "https://github.com/sebastianbergmann/type/issues",
"source": "https://github.com/sebastianbergmann/type/tree/2.3.1" "source": "https://github.com/sebastianbergmann/type/tree/2.3.2"
}, },
"funding": [ "funding": [
{ {
@ -13831,7 +13882,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-10-26T13:18:59+00:00" "time": "2021-06-04T13:02:07+00:00"
}, },
{ {
"name": "sebastian/version", "name": "sebastian/version",
@ -13888,16 +13939,16 @@
}, },
{ {
"name": "swagger-api/swagger-ui", "name": "swagger-api/swagger-ui",
"version": "v3.49.0", "version": "v3.50.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/swagger-api/swagger-ui.git", "url": "https://github.com/swagger-api/swagger-ui.git",
"reference": "bbfa31beae18df5118dfcdfec257bd64dc8f61a2" "reference": "91858cc811d3cddb45ef604365e2c88cd96e4ca0"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/swagger-api/swagger-ui/zipball/bbfa31beae18df5118dfcdfec257bd64dc8f61a2", "url": "https://api.github.com/repos/swagger-api/swagger-ui/zipball/91858cc811d3cddb45ef604365e2c88cd96e4ca0",
"reference": "bbfa31beae18df5118dfcdfec257bd64dc8f61a2", "reference": "91858cc811d3cddb45ef604365e2c88cd96e4ca0",
"shasum": "" "shasum": ""
}, },
"type": "library", "type": "library",
@ -13943,9 +13994,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/swagger-api/swagger-ui/issues", "issues": "https://github.com/swagger-api/swagger-ui/issues",
"source": "https://github.com/swagger-api/swagger-ui/tree/v3.49.0" "source": "https://github.com/swagger-api/swagger-ui/tree/v3.50.0"
}, },
"time": "2021-05-19T21:54:39+00:00" "time": "2021-06-03T21:00:28+00:00"
}, },
{ {
"name": "symfony/debug", "name": "symfony/debug",

View File

@ -14,8 +14,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true), 'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', 'invoicing.co'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
'app_version' => '5.2.5', 'app_version' => '5.2.6',
'app_tag' => '5.2.5-release', 'app_tag' => '5.2.6-release',
'minimum_client_version' => '5.0.16', 'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1', 'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', ''), 'api_secret' => env('API_SECRET', ''),
@ -148,6 +148,11 @@ return [
'disable_auto_update' => env('DISABLE_AUTO_UPDATE', false), 'disable_auto_update' => env('DISABLE_AUTO_UPDATE', false),
'invoiceninja_hosted_pdf_generation' => env('NINJA_HOSTED_PDF', false), 'invoiceninja_hosted_pdf_generation' => env('NINJA_HOSTED_PDF', false),
'ninja_stripe_key' => env('NINJA_STRIPE_KEY', null), 'ninja_stripe_key' => env('NINJA_STRIPE_KEY', null),
'wepay' => [
'environment' => env('WEPAY_ENVIRONMENT', 'stage'),
'client_id' => env('WEPAY_CLIENT_ID', ''),
'client_secret' => env('WEPAY_CLIENT_SECRET',''),
],
'ninja_stripe_publishable_key' => env('NINJA_PUBLISHABLE_KEY', null), 'ninja_stripe_publishable_key' => env('NINJA_PUBLISHABLE_KEY', null),
'ninja_stripe_client_id' => env('NINJA_STRIPE_CLIENT_ID', null), 'ninja_stripe_client_id' => env('NINJA_STRIPE_CLIENT_ID', null),
'ninja_default_company_id' => env('NINJA_COMPANY_ID', null), 'ninja_default_company_id' => env('NINJA_COMPANY_ID', null),

View File

@ -0,0 +1,31 @@
<?php
use App\Models\Gateway;
use App\Utils\Ninja;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class ActivateWePay extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
if(Gateway::count() >=1 && Ninja::isHosted())
Gateway::whereIn('id', [49])->update(['visible' => true]);
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@ -101,8 +101,9 @@ class PaymentLibrariesSeeder extends Seeder
if (Ninja::isHosted()) { if (Ninja::isHosted()) {
Gateway::whereIn('id', [20])->update(['visible' => 0]); Gateway::whereIn('id', [20])->update(['visible' => 0]);
Gateway::whereIn('id', [56])->update(['visible' => 1]); Gateway::whereIn('id', [56])->update(['visible' => 1]);
Gateway::whereIn('id', [49])->update(['visible' => 1]);
} }
Gateway::all()->each(function ($gateway) { Gateway::all()->each(function ($gateway) {
$gateway->site_url = $gateway->getHelp(); $gateway->site_url = $gateway->getHelp();
$gateway->save(); $gateway->save();

View File

@ -1 +1 @@
{"assets/images/google-icon.png":["assets/images/google-icon.png"],"assets/images/logo.png":["assets/images/logo.png"],"assets/images/payment_types/ach.png":["assets/images/payment_types/ach.png"],"assets/images/payment_types/amex.png":["assets/images/payment_types/amex.png"],"assets/images/payment_types/carteblanche.png":["assets/images/payment_types/carteblanche.png"],"assets/images/payment_types/dinerscard.png":["assets/images/payment_types/dinerscard.png"],"assets/images/payment_types/discover.png":["assets/images/payment_types/discover.png"],"assets/images/payment_types/jcb.png":["assets/images/payment_types/jcb.png"],"assets/images/payment_types/laser.png":["assets/images/payment_types/laser.png"],"assets/images/payment_types/maestro.png":["assets/images/payment_types/maestro.png"],"assets/images/payment_types/mastercard.png":["assets/images/payment_types/mastercard.png"],"assets/images/payment_types/other.png":["assets/images/payment_types/other.png"],"assets/images/payment_types/paypal.png":["assets/images/payment_types/paypal.png"],"assets/images/payment_types/solo.png":["assets/images/payment_types/solo.png"],"assets/images/payment_types/switch.png":["assets/images/payment_types/switch.png"],"assets/images/payment_types/unionpay.png":["assets/images/payment_types/unionpay.png"],"assets/images/payment_types/visa.png":["assets/images/payment_types/visa.png"],"packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf":["packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf"]} {"assets/images/google-icon.png":["assets/images/google-icon.png"],"assets/images/icon.png":["assets/images/icon.png"],"assets/images/payment_types/ach.png":["assets/images/payment_types/ach.png"],"assets/images/payment_types/amex.png":["assets/images/payment_types/amex.png"],"assets/images/payment_types/carteblanche.png":["assets/images/payment_types/carteblanche.png"],"assets/images/payment_types/dinerscard.png":["assets/images/payment_types/dinerscard.png"],"assets/images/payment_types/discover.png":["assets/images/payment_types/discover.png"],"assets/images/payment_types/jcb.png":["assets/images/payment_types/jcb.png"],"assets/images/payment_types/laser.png":["assets/images/payment_types/laser.png"],"assets/images/payment_types/maestro.png":["assets/images/payment_types/maestro.png"],"assets/images/payment_types/mastercard.png":["assets/images/payment_types/mastercard.png"],"assets/images/payment_types/other.png":["assets/images/payment_types/other.png"],"assets/images/payment_types/paypal.png":["assets/images/payment_types/paypal.png"],"assets/images/payment_types/solo.png":["assets/images/payment_types/solo.png"],"assets/images/payment_types/switch.png":["assets/images/payment_types/switch.png"],"assets/images/payment_types/unionpay.png":["assets/images/payment_types/unionpay.png"],"assets/images/payment_types/visa.png":["assets/images/payment_types/visa.png"],"packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf":["packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf"]}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

2
public/css/app.css vendored

File diff suppressed because one or more lines are too long

View File

@ -8,10 +8,11 @@ const RESOURCES = {
"version.json": "9fe5b22a16f39b766c8fdc35a24b3efa", "version.json": "9fe5b22a16f39b766c8fdc35a24b3efa",
"favicon.ico": "51636d3a390451561744c42188ccd628", "favicon.ico": "51636d3a390451561744c42188ccd628",
"manifest.json": "ce1b79950eb917ea619a0a30da27c6a3", "manifest.json": "ce1b79950eb917ea619a0a30da27c6a3",
"assets/AssetManifest.json": "659dcf9d1baf3aed3ab1b9c42112bf8f", "assets/AssetManifest.json": "7e49562f32e24a9e2557fe4178a84b79",
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "174c02fc4609e8fc4389f5d21f16a296", "assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "174c02fc4609e8fc4389f5d21f16a296",
"assets/fonts/MaterialIcons-Regular.otf": "1288c9e28052e028aba623321f7826ac", "assets/fonts/MaterialIcons-Regular.otf": "1288c9e28052e028aba623321f7826ac",
"assets/assets/images/google-icon.png": "0f118259ce403274f407f5e982e681c3", "assets/assets/images/google-icon.png": "0f118259ce403274f407f5e982e681c3",
"assets/assets/images/icon.png": "090f69e23311a4b6d851b3880ae52541",
"assets/assets/images/payment_types/solo.png": "2030c3ccaccf5d5e87916a62f5b084d6", "assets/assets/images/payment_types/solo.png": "2030c3ccaccf5d5e87916a62f5b084d6",
"assets/assets/images/payment_types/laser.png": "b4e6e93dd35517ac429301119ff05868", "assets/assets/images/payment_types/laser.png": "b4e6e93dd35517ac429301119ff05868",
"assets/assets/images/payment_types/maestro.png": "e533b92bfb50339fdbfa79e3dfe81f08", "assets/assets/images/payment_types/maestro.png": "e533b92bfb50339fdbfa79e3dfe81f08",
@ -27,11 +28,10 @@ const RESOURCES = {
"assets/assets/images/payment_types/dinerscard.png": "06d85186ba858c18ab7c9caa42c92024", "assets/assets/images/payment_types/dinerscard.png": "06d85186ba858c18ab7c9caa42c92024",
"assets/assets/images/payment_types/mastercard.png": "6f6cdc29ee2e22e06b1ac029cb52ef71", "assets/assets/images/payment_types/mastercard.png": "6f6cdc29ee2e22e06b1ac029cb52ef71",
"assets/assets/images/payment_types/other.png": "d936e11fa3884b8c9f1bd5c914be8629", "assets/assets/images/payment_types/other.png": "d936e11fa3884b8c9f1bd5c914be8629",
"assets/assets/images/logo.png": "090f69e23311a4b6d851b3880ae52541",
"assets/NOTICES": "687b68d41e137cfbdee105c0b9be3e9d", "assets/NOTICES": "687b68d41e137cfbdee105c0b9be3e9d",
"assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f", "assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f",
"favicon.png": "dca91c54388f52eded692718d5a98b8b", "favicon.png": "dca91c54388f52eded692718d5a98b8b",
"main.dart.js": "9bf3809dd480b5fa14847777a68f7833", "main.dart.js": "1225d7da63eaf3817e25a8b6726635cc",
"/": "23224b5e03519aaa87594403d54412cf" "/": "23224b5e03519aaa87594403d54412cf"
}; };

383
public/images/wepay.svg Normal file
View File

@ -0,0 +1,383 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="146.57001"
height="53.70924"
viewBox="0 0 38.779979 14.21057"
version="1.1"
id="svg3260"
inkscape:version="0.92.0 r15299"
sodipodi:docname="wepay.svg">
<defs
id="defs3254">
<clipPath
id="clipPath3278"
clipPathUnits="userSpaceOnUse">
<path
inkscape:connector-curvature="0"
id="path3276"
d="M 0,0 H 595.276 V 841.89 H 0 Z" />
</clipPath>
<clipPath
id="clipPath3288"
clipPathUnits="userSpaceOnUse">
<path
inkscape:connector-curvature="0"
id="path3286"
d="M 0,841.89 H 595.276 V 0 H 0 Z" />
</clipPath>
<clipPath
id="clipPath3318"
clipPathUnits="userSpaceOnUse">
<path
inkscape:connector-curvature="0"
id="path3316"
d="M 0,841.89 H 595.276 V 0 H 0 Z" />
</clipPath>
<clipPath
id="clipPath3326"
clipPathUnits="userSpaceOnUse">
<path
inkscape:connector-curvature="0"
id="path3324"
d="M 419.528,14.172 H 581.103 V 31.18 H 419.528 Z" />
</clipPath>
<clipPath
id="clipPath3340"
clipPathUnits="userSpaceOnUse">
<path
inkscape:connector-curvature="0"
id="path3338"
d="M 419.528,14.172 H 581.102 V 31.18 H 419.528 Z" />
</clipPath>
<clipPath
id="clipPath4412"
clipPathUnits="userSpaceOnUse">
<path
inkscape:connector-curvature="0"
id="path4410"
d="M 0,0 H 598.441 V 612 H 0 Z" />
</clipPath>
<clipPath
id="clipPath4436"
clipPathUnits="userSpaceOnUse">
<path
inkscape:connector-curvature="0"
id="path4434"
d="m 536.641,119.187 h 220.051 v 64.601 H 536.641 Z" />
</clipPath>
<clipPath
id="clipPath4640"
clipPathUnits="userSpaceOnUse">
<path
inkscape:connector-curvature="0"
id="path4638"
d="M 0,0 H 612 V 792 H 0 Z" />
</clipPath>
<clipPath
id="clipPath4648"
clipPathUnits="userSpaceOnUse">
<path
inkscape:connector-curvature="0"
id="path4646"
d="M 35,523.946 H 577 V 98.36 H 35 Z" />
</clipPath>
<radialGradient
id="radialGradient4660"
spreadMethod="pad"
gradientTransform="matrix(533.4704,0,0,-533.4704,126.08601,504.87846)"
gradientUnits="userSpaceOnUse"
r="1"
cy="0"
cx="0"
fy="0"
fx="0">
<stop
id="stop4654"
offset="0"
style="stop-opacity:1;stop-color:#ffffff" />
<stop
id="stop4656"
offset="0.288571"
style="stop-opacity:1;stop-color:#ffffff" />
<stop
id="stop4658"
offset="1"
style="stop-opacity:1;stop-color:#f58345" />
</radialGradient>
<clipPath
id="clipPath4686"
clipPathUnits="userSpaceOnUse">
<path
inkscape:connector-curvature="0"
id="path4684"
d="M 0,0 H 612 V 792 H 0 Z" />
</clipPath>
<clipPath
id="clipPath4722"
clipPathUnits="userSpaceOnUse">
<path
inkscape:connector-curvature="0"
id="path4720"
d="M 0,0 H 612 V 792 H 0 Z" />
</clipPath>
<linearGradient
id="linearGradient4744"
spreadMethod="pad"
gradientTransform="matrix(540,0,0,-540,36,610.90001)"
gradientUnits="userSpaceOnUse"
y2="0"
x2="1"
y1="0"
x1="0">
<stop
id="stop4740"
offset="0"
style="stop-opacity:1;stop-color:#808285" />
<stop
id="stop4742"
offset="1"
style="stop-opacity:1;stop-color:#4f4f51" />
</linearGradient>
<clipPath
id="clipPath4766"
clipPathUnits="userSpaceOnUse">
<path
inkscape:connector-curvature="0"
id="path4764"
d="M 44.28,414.765 H 255.575 V 495 H 44.28 Z" />
</clipPath>
<clipPath
id="clipPath4896"
clipPathUnits="userSpaceOnUse">
<path
inkscape:connector-curvature="0"
id="path4894"
d="m 36.544,99.36 h 539.4 v 422.445 h -539.4 z" />
</clipPath>
<clipPath
id="clipPath4904"
clipPathUnits="userSpaceOnUse">
<path
inkscape:connector-curvature="0"
id="path4902"
d="M -32.9452,542.473 H 652.766 V -381.128 H -32.9452 Z" />
</clipPath>
<clipPath
id="clipPath4936"
clipPathUnits="userSpaceOnUse">
<path
inkscape:connector-curvature="0"
id="path4934"
d="M 139.265,232.92 H 474.15 V 389.039 H 139.265 Z" />
</clipPath>
<mask
id="mask4940"
height="1"
width="1"
y="0"
x="0"
maskUnits="userSpaceOnUse">
<image
id="image4942"
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAdIAAADbCAAAAAD8c0+WAAAAAXNCSVQI5gpbmQAABJtJREFUeJzt3U9om2UcwPGkia1Zy9YqbqMOrA5HRUZxeFE8yFAY8zAvevGgZ0GGePUgzKuXOS86xJPgn5NjgjBYRaH+ISdZD26zW8VtnX+2lrazSZN48CCzSZb3fZ8+Sb79fo7vm/yeh355m7xvYcvlJEmSJEmSJG0Z+YhrPXz87oir9Ynzb14PPDFe0r1HX9wVbbE+Mv/e+zeDDoyVtPjWq2ORluo73xxeDjmuEHJYG28cK0Vaqf88MHY65LhISXec9Bpt7fG/fgg4bSDgrDZefzDOOv0p/87TAafFSbrv5SjL9K27ngs4LE7SVyaiLNO/RgPOipO0EmWVPhbyhj3SZ6niMWlPGAn4fMCkPeHJkXCzTNoTSgE7mLQn1APOMimOSXFMimNSHJPimBTHpDgmxTEpjklxTIpjUhyT4pgUx6Q4JsUxKY5JcUyKY1Ick+KYFMekOCbFMSmOSXFMimNSHJPimBTHpDgmxTEpjklxTIpjUhyT4pgUx6Q43UjaCPmv/Oj/unKVNrqx6JbRlaQx/yeTrcekOMUurGnRTeU3XhyT4pgUx6Q4JsUxKY5JcUyKY1Ick+KYFMekOCbFMSmOSXFMimNSHJPimBTHpDgmxTEpjklxTIpjUhyT4pgUx6Q4JsUxKY5JcUyKY1Ick+KYFMekOCbFMSmOSXFMimNSHJPimBTHpDgmxTEpjklxTIpjUhyT4pgUx6Q4JsUxKY5JcUyKY1Ick+KYFMekOCbFMSmOSXFMimNSHJPimBTHpDgmxTEpjklxTIpjUhyT4pgUx6Q4JsUxKY5JcUyKY1Ick+KYFMekOCbFMSmOSXFMimNSHJPimBTHpDgmxTEpjklxTIpjUhyT4pgUx6Q4JsUxKY5JcUyKY1Ick+KYFMekOCbFMSmOSXFMimNSHJPimBTHpDgmxTEpjklxTIpjUhyT4pgUx6Q4JsUxKY5JcUyKY1KcOEkrUVbpY42VcLOKnb6wNL57Z23k+ftSrTKR6l1byMjZ9XRv/G52/uertx/Kd/refLFYqI9/8Ui6lbVJXvuwXq3dfqjjq7RRreZyy8uht6RsllY3HEr2WdrxNa1ImhRJmLQQaCcKpEm/ZEnXLgTaicL4+/eNx5IlvfXVxUB7UQiV6V82Hkz2m7RxbW6lMu4nam+olj8+fmnjLX/SPIV9U0enSmG2pCxq66c+OrPW5ETS7zuNxUvXboxvD7EnZTJz6sRM06dyib/C1teuLq5Mbsu+JWWxXP7gs9l601NpPheH7j/07ORkti0pi4XpTy7+1GhxMs2NZu3GXPnK4J6OHzwpsPnP351eaHk23bOD1YXL51b/2D2Udk/K4Er55Kfn2pxPf0NSuvfwUwe3jaV+v5KrVa5/efn0b0u1di/Kco85ODj12EsPDQ9nGKEEKitnZs/+WK3e4WXZHhsMDN1z4NEXcrnCaGlnpkFqq7a0uJS/+fW331dutfpS9J/sT4LyjVwut//YkcyD1NL6ibf//PcH3YEAf1oZnXji0P4jPn3YRAPrOw5uLzR5RN9Mtqu0WBye2PXMngN7M01RJy7MzZTP/1qp3vFa/Qd4HqFCB+U7NwAAAABJRU5ErkJggg=="
preserveAspectRatio="none"
style="image-rendering:optimizeSpeed"
height="1"
width="1" />
</mask>
<style
id="style5609">.cls-1{fill:#508ecb;}.cls-2{fill:#32af4a;}.cls-3{fill:#231f20;}</style>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.509377"
inkscape:cx="72.784999"
inkscape:cy="26.354619"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
units="px"
inkscape:window-width="1280"
inkscape:window-height="744"
inkscape:window-x="-4"
inkscape:window-y="-4"
inkscape:window-maximized="1" />
<metadata
id="metadata3257">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-89.599445,-326.04814)">
<g
id="g5682"
transform="matrix(0.26458333,0,0,0.26458333,89.258134,325.73801)">
<path
d="m 27.08,27.23 h -2.6 L 19.1,10.51 H 19 L 13.63,27.23 H 11.08 L 1.79,2.39 h 5 l 5.52,16.14 H 12.4 L 17.53,2.39 h 3 l 5.16,16.14 h 0.09 L 31.3,2.39 h 5 z"
class="cls-1"
data-name="&lt;Compound Path&gt;"
id="_Compound_Path_"
inkscape:connector-curvature="0"
style="fill:#508ecb" />
<path
d="m 41.26,16.83 a 8.43,8.43 0 0 0 8.16,6.77 7.94,7.94 0 0 0 7.09,-4.17 h 4.66 a 12.66,12.66 0 0 1 -11.92,8.43 c -7,0 -12.65,-6.06 -12.65,-13.1 A 12.700946,12.700946 0 1 1 62,14.45 c 0,0.81 -0.09,2.06 -0.13,2.38 z m 16.06,-3.59 a 8.07,8.07 0 0 0 -16.06,0 z"
class="cls-1"
data-name="&lt;Compound Path&gt;"
id="_Compound_Path_2"
inkscape:connector-curvature="0"
style="fill:#508ecb" />
<path
d="m 65.52,2.39 h 4.26 V 6.2 h 0.09 a 10.49,10.49 0 0 1 8.84,-4.48 c 8.43,0 12.86,6.77 12.86,13.4 A 12.52,12.52 0 0 1 79,27.86 c -5.2,0 -7.8,-2.65 -8.74,-4.22 H 70.17 V 35.53 H 65.52 Z M 78.39,6 C 73.5,6 70.1,10.21 70.1,14.78 a 8.41,8.41 0 1 0 16.81,0.09 C 86.91,10.42 83.46,6 78.39,6 Z"
class="cls-2"
data-name="&lt;Compound Path&gt;"
id="_Compound_Path_3"
inkscape:connector-curvature="0"
style="fill:#32af4a" />
<path
d="m 115.56,27.23 v -3.86 h -0.09 A 9.5,9.5 0 0 1 107,27.86 12.75,12.75 0 0 1 93.82,14.86 C 93.82,8.81 98.08,1.68 107,1.68 a 9.82,9.82 0 0 1 8.43,4.17 h 0.09 V 2.39 h 4.67 V 27.23 Z M 107,6 c -5.74,0 -8.52,5 -8.52,8.87 a 8.57,8.57 0 1 0 17.13,0 A 8.48,8.48 0 0 0 107,6 Z"
class="cls-2"
data-name="&lt;Compound Path&gt;"
id="_Compound_Path_4"
inkscape:connector-curvature="0"
style="fill:#32af4a" />
<path
d="m 133.68,35.53 h -4.84 l 3.63,-8.79 -9.91,-24.35 h 5 l 7.31,19.28 7.49,-19.28 h 5 z"
class="cls-2"
data-name="&lt;Compound Path&gt;"
id="_Compound_Path_5"
inkscape:connector-curvature="0"
style="fill:#32af4a" />
<path
id="path5620"
d="m 78,41.32 a 0.46,0.46 0 0 0 -0.45,0.46 V 45 h 8.49 l -3.87,-3.68 z"
class="cls-3"
inkscape:connector-curvature="0"
style="fill:#231f20" />
<path
id="path5622"
d="M 86.4,46 A 0.47,0.47 0 0 0 85.94,45.54 H 82.72 V 54 l 3.68,-3.87 z"
class="cls-3"
inkscape:connector-curvature="0"
style="fill:#231f20" />
<path
id="path5624"
d="m 81.75,54.32 a 0.46,0.46 0 0 0 0.45,-0.46 v -3.22 h -8.5 l 3.87,3.68 z"
class="cls-3"
inkscape:connector-curvature="0"
style="fill:#231f20" />
<path
id="path5626"
d="m 73.39,49.67 a 0.47,0.47 0 0 0 0.46,0.46 h 3.22 v -8.5 l -3.68,3.87 z"
class="cls-3"
inkscape:connector-curvature="0"
style="fill:#231f20" />
<path
id="path5628"
d="M 34.44,42.87 V 46.8 H 29 v -3.93 h -2 v 9.9 h 2 v -4.25 h 5.47 v 4.25 h 2 v -9.9 z"
class="cls-3"
inkscape:connector-curvature="0"
style="fill:#231f20" />
<path
id="path5630"
d="m 60.93,42.87 v 9.89 h 8.74 L 68.56,51 h -5.63 v -2.5 h 5.46 v -1.66 h -5.46 v -2.27 h 5.62 l 1.09,-1.7 z"
class="cls-3"
inkscape:connector-curvature="0"
style="fill:#231f20" />
<path
id="path5632"
d="M 19.57,42.87 A 2.84,2.84 0 0 0 16.46,46 v 3.7 a 2.85,2.85 0 0 0 3.1,3.11 h 6.25 L 24.65,51 H 20 c -1,0 -1.43,-0.36 -1.43,-1.48 v -3.39 c 0,-1.09 0.36,-1.51 1.46,-1.51 h 4.67 l 1.11,-1.75 z"
class="cls-3"
inkscape:connector-curvature="0"
style="fill:#231f20" />
<path
id="path5634"
d="m 52.19,42.87 a 2.33,2.33 0 0 0 -2.42,2.57 v 0.47 a 2.34,2.34 0 0 0 2.36,2.67 h 4.14 c 0.43,0 0.78,0.07 0.78,0.8 v 0.84 c 0,0.65 -0.33,0.8 -0.79,0.8 h -5.45 l -1.12,1.74 h 6.7 a 2.41,2.41 0 0 0 2.71,-2.65 v -0.69 a 2.37,2.37 0 0 0 -2.6,-2.64 h -4 c -0.43,0 -0.74,-0.12 -0.74,-0.77 v -0.68 c 0,-0.56 0.21,-0.76 0.72,-0.76 h 5.19 l 1.09,-1.71 z"
class="cls-3"
inkscape:connector-curvature="0"
style="fill:#231f20" />
<path
id="path5636"
d="m 42.22,42.87 -4.69,9.9 h 2.21 l 0.92,-2.05 h 5.1 l 0.91,2.05 h 2.22 l -4.7,-9.9 z m 1,2.06 L 45,49 h -3.6 z"
class="cls-3"
inkscape:connector-curvature="0"
style="fill:#231f20" />
<path
id="path5638"
d="M 10.17,51.48 10,50.57 H 9.93 A 2.88,2.88 0 0 1 8.98,51.39 3,3 0 0 1 7.79,51.6 2.14,2.14 0 0 1 6.29,51.11 1.81,1.81 0 0 1 5.75,49.71 c 0,-1.29 1,-2 3.11,-2 h 1.08 v -0.4 A 1.6,1.6 0 0 0 9.62,46.2 1.34,1.34 0 0 0 8.62,45.84 4.18,4.18 0 0 0 6.81,46.33 L 6.51,45.59 A 4.48,4.48 0 0 1 8.64,45 a 2.5,2.5 0 0 1 1.7,0.5 2.14,2.14 0 0 1 0.55,1.64 v 4.37 z M 8,50.8 a 2,2 0 0 0 1.42,-0.5 1.83,1.83 0 0 0 0.52,-1.39 v -0.58 h -1 a 3.6,3.6 0 0 0 -1.67,0.36 1.08,1.08 0 0 0 -0.51,1 1,1 0 0 0 0.32,0.8 A 1.28,1.28 0 0 0 8,50.8 Z"
class="cls-3"
inkscape:connector-curvature="0"
style="fill:#231f20" />
<path
id="path5640"
d="m 94,51.6 a 2.75,2.75 0 0 1 -2.16,-0.86 3.51,3.51 0 0 1 -0.76,-2.42 3.67,3.67 0 0 1 0.77,-2.49 2.83,2.83 0 0 1 2.2,-0.83 4.9,4.9 0 0 1 0.93,0.1 3,3 0 0 1 0.72,0.24 l -0.3,0.82 a 4.13,4.13 0 0 0 -0.7,-0.21 2.88,2.88 0 0 0 -0.67,-0.09 c -1.3,0 -2,0.83 -2,2.5 a 3,3 0 0 0 0.47,1.81 1.67,1.67 0 0 0 1.42,0.63 4.3,4.3 0 0 0 1.64,-0.34 v 0.86 A 3.54,3.54 0 0 1 94,51.6 Z"
class="cls-3"
inkscape:connector-curvature="0"
style="fill:#231f20" />
<path
id="path5642"
d="M 102.57,48.27 A 3.52,3.52 0 0 1 101.78,50.72 2.77,2.77 0 0 1 99.6,51.6 3,3 0 0 1 98.07,51.2 2.71,2.71 0 0 1 97,50 4.08,4.08 0 0 1 96.64,48.23 3.54,3.54 0 0 1 97.42,45.79 2.75,2.75 0 0 1 99.64,45 a 2.72,2.72 0 0 1 2.14,0.9 3.56,3.56 0 0 1 0.79,2.37 z m -4.89,0 a 3,3 0 0 0 0.5,1.87 1.68,1.68 0 0 0 1.44,0.65 1.74,1.74 0 0 0 1.45,-0.64 3.05,3.05 0 0 0 0.49,-1.88 3,3 0 0 0 -0.49,-1.86 1.75,1.75 0 0 0 -1.46,-0.63 1.72,1.72 0 0 0 -1.44,0.62 3,3 0 0 0 -0.49,1.87 z"
class="cls-3"
inkscape:connector-curvature="0"
style="fill:#231f20" />
<path
id="path5644"
d="m 112.35,51.48 v -4.17 a 1.73,1.73 0 0 0 -0.33,-1.15 1.29,1.29 0 0 0 -1,-0.38 1.64,1.64 0 0 0 -1.34,0.52 2.47,2.47 0 0 0 -0.43,1.6 v 3.58 h -1 v -4.17 a 1.73,1.73 0 0 0 -0.33,-1.15 1.29,1.29 0 0 0 -1,-0.38 1.57,1.57 0 0 0 -1.34,0.55 3,3 0 0 0 -0.42,1.79 v 3.36 h -1 V 45.07 H 105 l 0.15,0.88 v 0 a 1.84,1.84 0 0 1 0.78,-0.73 2.29,2.29 0 0 1 1.12,-0.27 A 1.91,1.91 0 0 1 109,46 v 0 a 2,2 0 0 1 0.83,-0.79 2.5,2.5 0 0 1 1.24,-0.3 2.19,2.19 0 0 1 1.63,0.56 2.5,2.5 0 0 1 0.54,1.79 v 4.18 z"
class="cls-3"
inkscape:connector-curvature="0"
style="fill:#231f20" />
<path
id="path5646"
d="m 118.21,51.6 a 2.88,2.88 0 0 1 -1.15,-0.23 2.28,2.28 0 0 1 -0.87,-0.71 h -0.07 a 8,8 0 0 1 0.07,1.06 v 2.64 h -1 V 45.07 H 116 l 0.14,0.88 v 0 a 2.18,2.18 0 0 1 0.88,-0.76 2.58,2.58 0 0 1 1.14,-0.24 2.36,2.36 0 0 1 2,0.88 4.62,4.62 0 0 1 0,4.89 2.35,2.35 0 0 1 -1.95,0.88 z m -0.14,-5.82 a 1.75,1.75 0 0 0 -1.43,0.54 2.82,2.82 0 0 0 -0.45,1.73 v 0.22 a 3.18,3.18 0 0 0 0.45,1.93 1.73,1.73 0 0 0 1.45,0.59 1.5,1.5 0 0 0 1.3,-0.68 3.2,3.2 0 0 0 0.47,-1.85 3.1,3.1 0 0 0 -0.47,-1.84 1.53,1.53 0 0 0 -1.32,-0.64 z"
class="cls-3"
inkscape:connector-curvature="0"
style="fill:#231f20" />
<path
id="path5648"
d="m 126.41,51.48 -0.19,-0.91 v 0 a 2.88,2.88 0 0 1 -1,0.82 3,3 0 0 1 -1.19,0.21 2.14,2.14 0 0 1 -1.5,-0.49 1.81,1.81 0 0 1 -0.54,-1.4 c 0,-1.29 1,-2 3.11,-2 h 1.08 v -0.4 a 1.6,1.6 0 0 0 -0.32,-1.11 1.34,1.34 0 0 0 -1,-0.36 4.18,4.18 0 0 0 -1.81,0.49 l -0.3,-0.74 a 4.48,4.48 0 0 1 2.17,-0.55 2.5,2.5 0 0 1 1.7,0.5 2.14,2.14 0 0 1 0.55,1.64 v 4.37 z m -2.19,-0.68 a 2,2 0 0 0 1.42,-0.5 1.83,1.83 0 0 0 0.52,-1.39 v -0.58 h -1 a 3.6,3.6 0 0 0 -1.67,0.36 1.08,1.08 0 0 0 -0.51,1 1,1 0 0 0 0.32,0.8 1.28,1.28 0 0 0 0.92,0.31 z"
class="cls-3"
inkscape:connector-curvature="0"
style="fill:#231f20" />
<path
id="path5650"
d="m 133.42,51.48 v -4.15 a 1.72,1.72 0 0 0 -0.35,-1.17 1.49,1.49 0 0 0 -1.12,-0.38 1.84,1.84 0 0 0 -1.47,0.54 2.7,2.7 0 0 0 -0.47,1.8 v 3.36 h -1 v -6.41 h 0.79 L 130,46 v 0 a 2,2 0 0 1 0.84,-0.74 2.78,2.78 0 0 1 1.2,-0.26 2.44,2.44 0 0 1 1.74,0.56 2.38,2.38 0 0 1 0.59,1.79 v 4.18 z"
class="cls-3"
inkscape:connector-curvature="0"
style="fill:#231f20" />
<path
id="path5652"
d="m 135.28,45.07 h 1 l 1.4,3.66 a 12.69,12.69 0 0 1 0.57,1.8 h 0.05 c 0,-0.19 0.16,-0.53 0.32,-1 0.16,-0.47 0.69,-2 1.59,-4.44 h 1 l -2.76,7.3 a 3.74,3.74 0 0 1 -0.95,1.54 2,2 0 0 1 -1.34,0.45 3.71,3.71 0 0 1 -0.88,-0.1 V 53.5 a 3.14,3.14 0 0 0 0.72,0.07 1.47,1.47 0 0 0 1.42,-1.12 l 0.36,-0.91 z"
class="cls-3"
inkscape:connector-curvature="0"
style="fill:#231f20" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,2 @@
/*! For license information please see wepay-bank-account.js.LICENSE.txt */
!function(e){var n={};function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(n){return e[n]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="/",t(t.s=20)}({20:function(e,n,t){e.exports=t("bIGw")},bIGw:function(e,n){function t(e,n){for(var t=0;t<n.length;t++){var r=n[t];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var r=function(){function e(){!function(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this,e)}var n,r,o;return n=e,(r=[{key:"initializeWePay",value:function(){var e,n=null===(e=document.querySelector('meta[name="wepay-environment"]'))||void 0===e?void 0:e.content;return WePay.set_endpoint("staging"===n?"stage":"production"),this}},{key:"showBankPopup",value:function(){var e,n;WePay.bank_account.create({client_id:null===(e=document.querySelector("meta[name=wepay-client-id]"))||void 0===e?void 0:e.content,email:null===(n=document.querySelector("meta[name=contact-email]"))||void 0===n?void 0:n.content},(function(e){e.error?(errors.textContent="",errors.textContent=e.error_description,errors.hidden=!1):(document.querySelector('input[name="bank_account_id"]').value=e.bank_account_id,document.getElementById("server_response").submit())}),(function(e){e.error&&(errors.textContent="",errors.textContent=e.error_description,errors.hidden=!1)}))}},{key:"handle",value:function(){this.initializeWePay().showBankPopup()}}])&&t(n.prototype,r),o&&t(n,o),e}();document.addEventListener("DOMContentLoaded",(function(){(new r).handle()}))}});

View File

@ -0,0 +1,9 @@
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,9 @@
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

159477
public/main.dart.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

159679
public/main.foss.dart.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,10 +1,11 @@
{ {
"/js/app.js": "/js/app.js?id=696e8203d5e8e7cf5ff5", "/js/app.js": "/js/app.js?id=696e8203d5e8e7cf5ff5",
"/css/app.css": "/css/app.css?id=362fcaff4938566f7508", "/css/app.css": "/css/app.css?id=b3b5fbe4dbfcef5b5f8e",
"/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=a09bb529b8e1826f13b4", "/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=a09bb529b8e1826f13b4",
"/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=8ce8955ba775ea5f47d1", "/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=8ce8955ba775ea5f47d1",
"/js/clients/linkify-urls.js": "/js/clients/linkify-urls.js?id=0dc8c34010d09195d2f7", "/js/clients/linkify-urls.js": "/js/clients/linkify-urls.js?id=0dc8c34010d09195d2f7",
"/js/clients/payment_methods/authorize-authorize-card.js": "/js/clients/payment_methods/authorize-authorize-card.js?id=206d7de4ac97612980ff", "/js/clients/payment_methods/authorize-authorize-card.js": "/js/clients/payment_methods/authorize-authorize-card.js?id=206d7de4ac97612980ff",
"/js/clients/payment_methods/wepay-bank-account.js": "/js/clients/payment_methods/wepay-bank-account.js?id=8fea0be371d430064a89",
"/js/clients/payments/authorize-credit-card-payment.js": "/js/clients/payments/authorize-credit-card-payment.js?id=a376eff2227da398b0ba", "/js/clients/payments/authorize-credit-card-payment.js": "/js/clients/payments/authorize-credit-card-payment.js?id=a376eff2227da398b0ba",
"/js/clients/payments/braintree-credit-card.js": "/js/clients/payments/braintree-credit-card.js?id=81957e7cb1cb49f23b90", "/js/clients/payments/braintree-credit-card.js": "/js/clients/payments/braintree-credit-card.js?id=81957e7cb1cb49f23b90",
"/js/clients/payments/braintree-paypal.js": "/js/clients/payments/braintree-paypal.js?id=c35db3cbb65806ab6a8a", "/js/clients/payments/braintree-paypal.js": "/js/clients/payments/braintree-paypal.js?id=c35db3cbb65806ab6a8a",
@ -14,6 +15,7 @@
"/js/clients/payments/stripe-alipay.js": "/js/clients/payments/stripe-alipay.js?id=665ddf663500767f1a17", "/js/clients/payments/stripe-alipay.js": "/js/clients/payments/stripe-alipay.js?id=665ddf663500767f1a17",
"/js/clients/payments/stripe-credit-card.js": "/js/clients/payments/stripe-credit-card.js?id=f1719b79a2bb274d3f64", "/js/clients/payments/stripe-credit-card.js": "/js/clients/payments/stripe-credit-card.js?id=f1719b79a2bb274d3f64",
"/js/clients/payments/stripe-sofort.js": "/js/clients/payments/stripe-sofort.js?id=08bf4871826e8b18b804", "/js/clients/payments/stripe-sofort.js": "/js/clients/payments/stripe-sofort.js?id=08bf4871826e8b18b804",
"/js/clients/payments/wepay-credit-card.js": "/js/clients/payments/wepay-credit-card.js?id=eab1ea239a721bea90c4",
"/js/clients/quotes/action-selectors.js": "/js/clients/quotes/action-selectors.js?id=1b8f9325aa6e8595e7fa", "/js/clients/quotes/action-selectors.js": "/js/clients/quotes/action-selectors.js?id=1b8f9325aa6e8595e7fa",
"/js/clients/quotes/approve.js": "/js/clients/quotes/approve.js?id=85bcae0a646882e56b12", "/js/clients/quotes/approve.js": "/js/clients/quotes/approve.js?id=85bcae0a646882e56b12",
"/js/clients/shared/multiple-downloads.js": "/js/clients/shared/multiple-downloads.js?id=5c35d28cf0a3286e7c45", "/js/clients/shared/multiple-downloads.js": "/js/clients/shared/multiple-downloads.js?id=5c35d28cf0a3286e7c45",

View File

@ -0,0 +1,52 @@
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
class WePayBank {
initializeWePay() {
let environment = document.querySelector('meta[name="wepay-environment"]')?.content;
WePay.set_endpoint(environment === 'staging' ? 'stage' : 'production');
return this;
}
showBankPopup() {
WePay.bank_account.create({
client_id: document.querySelector('meta[name=wepay-client-id]')?.content,
email: document.querySelector('meta[name=contact-email]')?.content
}, function (data) {
if (data.error) {
errors.textContent = '';
errors.textContent = data.error_description;
errors.hidden = false;
} else {
document.querySelector('input[name="bank_account_id"]').value = data.bank_account_id;
document.getElementById('server_response').submit();
}
}, function (data) {
if (data.error) {
errors.textContent = '';
errors.textContent = data.error_description;
errors.hidden = false;
}
}
);
}
handle() {
this
.initializeWePay()
.showBankPopup();
}
}
document.addEventListener('DOMContentLoaded', () => {
new WePayBank().handle();
});

View File

@ -0,0 +1,194 @@
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
let action = document.querySelector('meta[name="wepay-action"]')?.content;
class WePayCreditCard {
constructor(action = 'payment') {
this.action = action;
this.errors = document.getElementById('errors');
}
initializeWePay() {
let environment = document.querySelector('meta[name="wepay-environment"]')?.content;
WePay.set_endpoint(environment === 'staging' ? 'stage' : 'production');
return this;
}
validateCreditCardFields() {
this.myCard = $('#my-card');
if (document.getElementById('cardholder_name') === "") {
document.getElementById('cardholder_name').focus();
this.errors.textContent = "Cardholder name required.";
this.errors.hidden = false;
return;
} else if (this.myCard.CardJs('cardNumber') === "") {
document.getElementById('card_number').focus();
this.errors.textContent = "Card number required.";
this.errors.hidden = false;
return;
} else if (this.myCard.CardJs('cvc') === "") {
document.getElementById('cvv').focus();
this.errors.textContent = "CVV number required.";
this.errors.hidden = false;
return;
} else if (this.myCard.CardJs('expiryMonth') === "") {
// document.getElementById('expiry_month').focus();
this.errors.textContent = "Expiry Month number required.";
this.errors.hidden = false;
return;
} else if (this.myCard.CardJs('expiryYear') === "") {
// document.getElementById('expiry_year').focus();
this.errors.textContent = "Expiry Year number required.";
this.errors.hidden = false;
return;
}
return true;
}
handleAuthorization() {
if (!this.validateCreditCardFields()) {
return;
}
let cardButton = document.getElementById('card_button');
cardButton.disabled = true;
cardButton.querySelector('svg').classList.remove('hidden');
cardButton.querySelector('span').classList.add('hidden');
WePay.credit_card.create({
client_id: document.querySelector('meta[name=wepay-client-id]').content,
user_name: document.getElementById('cardholder_name').value,
email: document.querySelector('meta[name=contact-email]').content,
cc_number: this.myCard.CardJs('cardNumber'),
cvv: this.myCard.CardJs('cvc'),
expiration_month: this.myCard.CardJs('expiryMonth'),
expiration_year: this.myCard.CardJs('expiryYear'),
address: {
postal_code: document.querySelector(['meta[name=client-postal-code']).content,
}
}, (data) => {
if (data.error) {
cardButton = document.getElementById('card_button');
cardButton.disabled = false;
cardButton.querySelector('svg').classList.add('hidden');
cardButton.querySelector('span').classList.remove('hidden');
this.errors.textContent = '';
this.errors.textContent = data.error_description;
this.errors.hidden = false;
} else {
document.querySelector('input[name="credit_card_id"]').value = data.credit_card_id;
document.getElementById('server_response').submit();
}
})
}
completePaymentUsingToken(token) {
document.querySelector('input[name="credit_card_id"]').value = null;
document.querySelector('input[name="token"]').value = token;
document.getElementById('server-response').submit();
}
completePaymentWithoutToken() {
if (!this.validateCreditCardFields()) {
return;
}
WePay.credit_card.create({
client_id: document.querySelector('meta[name=wepay-client-id]').content,
user_name: document.getElementById('cardholder_name').value,
email: document.querySelector('meta[name=contact-email]').content,
cc_number: this.myCard.CardJs('cardNumber'),
cvv: this.myCard.CardJs('cvc'),
expiration_month: this.myCard.CardJs('expiryMonth'),
expiration_year: this.myCard.CardJs('expiryYear'),
address: {
postal_code: document.querySelector(['meta[name=client-postal-code']).content,
}
}, (data) => {
if (data.error) {
this.payNowButton.disabled = false;
this.payNowButton.querySelector('svg').classList.add('hidden');
this.payNowButton.querySelector('span').classList.remove('hidden');
this.errors.textContent = '';
this.errors.textContent = data.error_description;
this.errors.hidden = false;
} else {
document.querySelector('input[name="credit_card_id"]').value = data.credit_card_id;
document.querySelector('input[name="token"]').value = null;
document.getElementById('server-response').submit();
}
})
}
handle() {
this.initializeWePay();
if (this.action === 'authorize') {
document
.getElementById('card_button')
.addEventListener('click', () => this.handleAuthorization());
} else if (this.action === 'payment') {
Array
.from(document.getElementsByClassName('toggle-payment-with-token'))
.forEach((element) => element.addEventListener('click', (e) => {
document.getElementById('save-card--container').style.display = 'none';
document.getElementById('wepay--credit-card-container').style.display = 'none';
document.getElementById('token').value = e.target.dataset.token;
}));
document
.getElementById('toggle-payment-with-credit-card')
.addEventListener('click', (e) => {
document.getElementById('save-card--container').style.display = 'grid';
document.getElementById('wepay--credit-card-container').style.display = 'flex';
document.getElementById('token').value = null;
});
document
.getElementById('pay-now')
.addEventListener('click', () => {
this.payNowButton = document.getElementById('pay-now');
this.payNowButton.disabled = true;
this.payNowButton.querySelector('svg').classList.remove('hidden');
this.payNowButton.querySelector('span').classList.add('hidden');
let tokenInput = document.querySelector('input[name=token]');
let storeCard = document.querySelector('input[name=token-billing-checkbox]:checked');
if (storeCard) {
document.getElementById("store_card").value = storeCard.value;
}
if (tokenInput.value) {
return this.completePaymentUsingToken(tokenInput.value);
}
return this.completePaymentWithoutToken();
});
}
}
}
new WePayCreditCard(action).handle();

View File

@ -3970,7 +3970,7 @@ $LANG = array(
'details_of_recurring_invoice' => 'Here are some details about recurring invoice', 'details_of_recurring_invoice' => 'Here are some details about recurring invoice',
'cancellation' => 'Cancellation', 'cancellation' => 'Cancellation',
'about_cancellation' => 'In case you want to stop the recurring invoice, please click the request the cancellation.', 'about_cancellation' => 'In case you want to stop the recurring invoice, please click the request the cancellation.',
'cancellation_warning' => 'Warning! You are requesting a cancellation of this service.\n Your service may be cancelled with no further notification to you.', 'cancellation_warning' => 'Warning! You are requesting a cancellation of this service. Your service may be cancelled with no further notification to you.',
'cancellation_pending' => 'Cancellation pending, we\'ll be in touch!', 'cancellation_pending' => 'Cancellation pending, we\'ll be in touch!',
'list_of_payments' => 'List of payments', 'list_of_payments' => 'List of payments',
'payment_details' => 'Details of the payment', 'payment_details' => 'Details of the payment',
@ -4267,6 +4267,7 @@ $LANG = array(
'company_import_failure_subject' => 'Error importing :company', 'company_import_failure_subject' => 'Error importing :company',
'company_import_failure_body' => 'There was an error importing the company data, the error message was:', 'company_import_failure_body' => 'There was an error importing the company data, the error message was:',
'recurring_invoice_due_date' => 'Due Date', 'recurring_invoice_due_date' => 'Due Date',
'amount_cents' => 'Amount in pennies,pence or cents',
); );
return $LANG; return $LANG;

View File

@ -1,6 +1,6 @@
@component('email.template.admin', ['logo' => $logo ?? 'https://www.invoiceninja.com/wp-content/uploads/2015/10/logo-white-horizontal-1.png']) @component('email.template.admin', ['logo' => $logo ?? 'https://www.invoiceninja.com/wp-content/uploads/2015/10/logo-white-horizontal-1.png'])
{{-- Body --}} {{-- Body --}}
{{ $message }} {{ $support_message }}
{!! str_replace('\n', '<br>', $system_info) !!} {!! str_replace('\n', '<br>', $system_info) !!}

View File

@ -121,6 +121,10 @@
{{ $slot ?? '' }} {{ $slot ?? '' }}
{!! $body ?? '' !!} {!! $body ?? '' !!}
@isset($signature)
{{ nl2br($signature) }}
@endisset
<div> <div>
<a href="#" <a href="#"

View File

@ -10,11 +10,11 @@
<input type="hidden" name="customer" value="{{ $token->gateway_customer_reference }}"> <input type="hidden" name="customer" value="{{ $token->gateway_customer_reference }}">
<input type="hidden" name="source" value="{{ $token->token }}"> <input type="hidden" name="source" value="{{ $token->token }}">
@component('portal.ninja2020.components.general.card-element', ['title' => '#1 ' . ctrans('texts.amount')]) @component('portal.ninja2020.components.general.card-element', ['title' => '#1 ' . ctrans('texts.amount_cents')])
<input type="text" name="transactions[]" class="w-full input" required data-cy="verification-1st"> <input type="text" name="transactions[]" class="w-full input" required data-cy="verification-1st">
@endcomponent @endcomponent
@component('portal.ninja2020.components.general.card-element', ['title' => '#2 ' . ctrans('texts.amount')]) @component('portal.ninja2020.components.general.card-element', ['title' => '#2 ' . ctrans('texts.amount_cents')])
<input type="text" name="transactions[]" class="w-full input" required data-cy="verification-2nd"> <input type="text" name="transactions[]" class="w-full input" required data-cy="verification-2nd">
@endcomponent @endcomponent

View File

@ -0,0 +1,50 @@
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.credit_card'), 'card_title' => ctrans('texts.credit_card')])
@section('gateway_head')
<meta name="wepay-environment" content="{{ config('ninja.wepay.environment') }}">
<meta name="wepay-action" content="authorize">
<meta name="wepay-client-id" content="{{ config('ninja.wepay.client_id') }}">
<meta name="contact-email" content="{{ $contact->email }}">
<meta name="client-postal-code" content="{{ $contact->client->postal_code }}">
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="{{ asset('js/clients/payments/card-js.min.js') }}"></script>
<link href="{{ asset('css/card-js.min.css') }}" rel="stylesheet" type="text/css">
<script type="text/javascript" src="https://static.wepay.com/min/js/tokenization.4.latest.js"></script>
@endsection
@section('gateway_content')
<form action="{{ route('client.payment_methods.store', ['method' => App\Models\GatewayType::CREDIT_CARD]) }}"
method="post" id="server_response">
@csrf
<input type="hidden" name="company_gateway_id" value="{{ $gateway->company_gateway->id }}">
<input type="hidden" name="payment_method_id" value="1">
<input type="hidden" name="gateway_response" id="gateway_response">
<input type="hidden" name="is_default" id="is_default">
<input type="hidden" name="credit_card_id" id="credit_card_id">
</form>
@if(!Request::isSecure())
<p class="alert alert-failure">{{ ctrans('texts.https_required') }}</p>
@endif
<div class="alert alert-failure mb-4" hidden id="errors"></div>
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.method')])
{{ ctrans('texts.credit_card') }}
@endcomponent
@include('portal.ninja2020.gateways.wepay.includes.credit_card')
@component('portal.ninja2020.gateways.includes.pay_now', ['id' => 'card_button'])
{{ ctrans('texts.add_payment_method') }}
@endcomponent
@endsection
@section('gateway_footer')
<script src="{{ asset('js/clients/payments/wepay-credit-card.js') }}"></script>
@endsection

View File

@ -0,0 +1,32 @@
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.credit_card'), 'card_title' => ctrans('texts.bank_transfer')])
@section('gateway_head')
<meta name="wepay-environment" content="{{ config('ninja.wepay.environment') }}">
<meta name="wepay-client-id" content="{{ config('ninja.wepay.client_id') }}">
<meta name="contact-email" content="{{ $contact->email }}">
<script type="text/javascript" src="https://static.wepay.com/min/js/tokenization.4.latest.js"></script>
@endsection
@section('gateway_content')
<form action="{{ route('client.payment_methods.store', ['method' => App\Models\GatewayType::BANK_TRANSFER]) }}"
method="post" id="server_response">
@csrf
<input type="hidden" name="company_gateway_id" value="{{ $gateway->company_gateway->id }}">
<input type="hidden" name="payment_method_id" value="2">
<input type="hidden" name="is_default" id="is_default">
<input type="hidden" name="bank_account_id" id="bank_account_id">
</form>
<div class="alert alert-failure mb-4" hidden id="errors"></div>
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.method')])
{{ ctrans('texts.bank_account') }}
@endcomponent
@endsection
@section('gateway_footer')
<script src="{{ asset('js/clients/payment_methods/wepay-bank-account.js') }}"></script>
@endsection

View File

@ -0,0 +1,24 @@
@extends('portal.ninja2020.layout.payments', ['gateway_title' => 'ACH (Verification)', 'card_title' => 'ACH (Verification)'])
@section('gateway_content')
@if(session()->has('error'))
<div class="alert alert-failure mb-4">{{ session('error') }}</div>
@endif
<form method="POST">
@csrf
<input type="hidden" name="token" value="{{ $token->token }}">
@component('portal.ninja2020.components.general.card-element', ['title' => '#1 ' . ctrans('texts.amount_cents')])
<input type="text" name="transactions[]" class="w-full input" required data-cy="verification-1st">
@endcomponent
@component('portal.ninja2020.components.general.card-element', ['title' => '#2 ' . ctrans('texts.amount_cents')])
<input type="text" name="transactions[]" class="w-full input" required data-cy="verification-2nd">
@endcomponent
@component('portal.ninja2020.gateways.includes.pay_now', ['type' => 'submit'])
{{ ctrans('texts.complete_verification')}}
@endcomponent
</form>
@endsection

View File

@ -0,0 +1,57 @@
@extends('portal.ninja2020.layout.payments', ['gateway_title' => 'ACH', 'card_title' => 'ACH'])
@section('gateway_content')
@if(count($tokens) > 0)
<div class="alert alert-failure mb-4" hidden id="errors"></div>
@include('portal.ninja2020.gateways.includes.payment_details')
<form action="{{ route('client.payments.response') }}" method="post" id="server-response">
@csrf
<input type="hidden" name="company_gateway_id" value="{{ $gateway->getCompanyGatewayId() }}">
<input type="hidden" name="payment_method_id" value="{{ $payment_method_id }}">
<input type="hidden" name="amount" value="{{ $amount }}">
<input type="hidden" name="currency" value="{{ $currency }}">
<input type="hidden" name="payment_hash" value="{{ $payment_hash }}">
<input type="hidden" name="source" value="">
</form>
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')])
@if(count($tokens) > 0)
@foreach($tokens as $token)
<label class="mr-4">
<input
type="radio"
data-token="{{ $token->hashed_id }}"
name="payment-type"
class="form-radio cursor-pointer toggle-payment-with-token"/>
<span class="ml-1 cursor-pointer">{{ ctrans('texts.bank_transfer') }} (*{{ $token->meta->last4 }})</span>
</label>
@endforeach
@endisset
@endcomponent
@else
@component('portal.ninja2020.components.general.card-element-single', ['title' => 'ACH', 'show_title' => false])
<span>{{ ctrans('texts.bank_account_not_linked') }}</span>
<a class="button button-link text-primary"
href="{{ route('client.payment_methods.index') }}">{{ ctrans('texts.add_payment_method') }}</a>
@endcomponent
@endif
@include('portal.ninja2020.gateways.includes.pay_now')
@endsection
@push('footer')
<script>
Array
.from(document.getElementsByClassName('toggle-payment-with-token'))
.forEach((element) => element.addEventListener('click', (element) => {
document.querySelector('input[name=source]').value = element.target.dataset.token;
}));
document.getElementById('pay-now').addEventListener('click', function () {
document.getElementById('server-response').submit();
});
</script>
@endpush

View File

@ -0,0 +1,75 @@
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.credit_card'), 'card_title' => ctrans('texts.credit_card')])
@section('gateway_head')
<meta name="wepay-environment" content="{{ config('ninja.wepay.environment') }}">
<meta name="wepay-action" content="payment">
<meta name="wepay-client-id" content="{{ config('ninja.wepay.client_id') }}">
<meta name="contact-email" content="{{ $contact->email }}">
<meta name="client-postal-code" content="{{ $contact->client->postal_code }}">
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="{{ asset('js/clients/payments/card-js.min.js') }}"></script>
<link href="{{ asset('css/card-js.min.css') }}" rel="stylesheet" type="text/css">
<script type="text/javascript" src="https://static.wepay.com/min/js/tokenization.4.latest.js"></script>
@endsection
@section('gateway_content')
<form action="{{ route('client.payments.response') }}" method="post" id="server-response">
@csrf
<input type="hidden" name="gateway_response">
<input type="hidden" name="store_card" id="store_card">
<input type="hidden" name="payment_hash" value="{{ $payment_hash }}">
<input type="hidden" name="company_gateway_id" value="{{ $gateway->getCompanyGatewayId() }}">
<input type="hidden" name="payment_method_id" value="1">
<input type="hidden" name="token" id="token" value="">
<input type="hidden" name="credit_card_id" id="credit_card_id" value="">
</form>
<div class="alert alert-failure mb-4" hidden id="errors"></div>
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_type')])
{{ ctrans('texts.credit_card') }}
@endcomponent
@include('portal.ninja2020.gateways.includes.payment_details')
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')])
@if(count($tokens) > 0)
@foreach($tokens as $token)
<label class="mr-4">
<input
type="radio"
data-token="{{ $token->token }}"
name="payment-type"
class="form-radio cursor-pointer toggle-payment-with-token"/>
<span class="ml-1 cursor-pointer">**** {{ optional($token->meta)->last4 }}</span>
</label>
@endforeach
@endisset
<label>
<input
type="radio"
id="toggle-payment-with-credit-card"
class="form-radio cursor-pointer"
name="payment-type"
checked/>
<span class="ml-1 cursor-pointer">{{ __('texts.new_card') }}</span>
</label>
@endcomponent
@include('portal.ninja2020.gateways.includes.save_card')
@include('portal.ninja2020.gateways.wepay.includes.credit_card')
@include('portal.ninja2020.gateways.includes.pay_now')
@endsection
@section('gateway_footer')
<script src="{{ asset('js/clients/payments/wepay-credit-card.js') }}"></script>
@endsection

View File

@ -0,0 +1,12 @@
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
style="display: flex!important; justify-content: center!important;" id="wepay--credit-card-container">
<div class="card-js" id="my-card" data-capture-name="true">
<input class="name" id="cardholder_name" name="card-holders-name" placeholder="{{ ctrans('texts.name')}}" required>
<input class="card-number my-custom-class" id="card_number" name="card-number" required>
<input class="expiry-month" name="expiry-month" id="expiration_month" required>
<input class="expiry-year" name="expiry-year" id="expiration_year" required>
<input class="cvc" name="cvc" id="cvv" required>
</div>
<div id="errors"></div>
</div>

View File

@ -0,0 +1,24 @@
@extends('portal.ninja2020.layout.clean', ['custom_body_class' => 'bg-gray-50'])
@section('meta_title', ctrans('texts.sign_up_with_wepay'))
@section('body')
<div class="flex flex-col justify-center items-center mt-10">
<img src="{{ asset('images/wepay.svg') }}" alt="We Pay">
</div>
<div class="flex flex-col justify-center items-center mt-10">
<h1>Wepay setup complete:</h1>
</div>
<div class="flex flex-col justify-center items-center mt-10">
@if(isset($message))
{{ $message ?? '' }}
@endif
</div>
</div>
@endsection
@push('footer')
<script>
</script>
@endpush

View File

@ -0,0 +1,15 @@
@extends('portal.ninja2020.layout.clean', ['custom_body_class' => 'bg-gray-50'])
@section('meta_title', ctrans('texts.sign_up_with_wepay'))
@section('body')
<div class="flex flex-col justify-center items-center mt-10">
<img src="{{ asset('images/wepay.svg') }}" alt="We Pay">
</div>
@livewire('wepay-signup', ['user_id' => $user_id, 'company' => $company])
@endsection
@push('footer')
<script>
</script>
@endpush

View File

@ -0,0 +1,285 @@
<div class="flex flex-col justify-center items-center my-10">
<form wire:submit.prevent="submit">
@csrf
@method('POST')
<div class="shadow overflow-hidden rounded">
<div class="px-4 py-5 bg-white sm:p-6">
<div class="grid grid-cols-6 gap-6 max-w-4xl">
<div class="col-span-6 sm:col-span-3">
<label for="first_name" class="input-label">@lang('texts.first_name')</label>
<input id="first_name" class="input w-full" name="first_name" wire:model.defer="first_name"/>
@error('first_name')
<div class="validation validation-fail">
{{ $message }}
</div>
@enderror
</div>
<div class="col-span-6 sm:col-span-3">
<label for="last_name" class="input-label">@lang('texts.last_name')</label>
<input id="last_name" class="input w-full" name="last_name" wire:model.defer="last_name"/>
@error('last_name')
<div class="validation validation-fail">
{{ $message }}
</div>
@enderror
</div>
<div class="col-span-6 sm:col-span-4">
<label for="email_address" class="input-label">@lang('texts.email_address')</label>
<input id="email_address" class="input w-full" type="email" name="email"
wire:model.defer="email" disabled="true"/>
@error('email')
<div class="validation validation-fail">
{{ $message }}
</div>
@enderror
</div>
<div class="col-span-6 sm:col-span-4">
<label for="company_name" class="input-label">@lang('texts.company_name')</label>
<input id="company_name" class="input w-full" name="company_name"
wire:model.defer="company_name"/>
@error('company_name')
<div class="validation validation-fail">
{{ $message }}
</div>
@enderror
</div>
<div class="col-span-6 sm:col-span-4 flex items-center">
<label for="country" class="input-label mr-4">@lang('texts.country')</label>
<div class="radio mr-4">
<input class="form-radio cursor-pointer" type="radio" value="US" name="country" checked
wire:model.defer="country">
<span>{{ ctrans('texts.country_United States') }}</span>
</div>
<div class="radio mr-4">
<input class="form-radio cursor-pointer" type="radio" value="CA" name="country"
wire:model.defer="country">
<span>{{ ctrans('texts.country_Canada') }}</span>
</div>
<div class="radio mr-4">
<input class="form-radio cursor-pointer" type="radio" value="GB" name="country"
wire:model.defer="country">
<span>{{ ctrans('texts.country_United Kingdom') }}</span>
</div>
</div>
@if($country == 'CA')
<div class="col-span-6 sm:col-span-4 {{ $country != 'CA' ? 'hidden' : 'block' }}">
<label for="country" class="input-label">@lang('texts.debit_cards')</label>
<div class="checkbox">
<input class="form-checkbox cursor-pointer mr-2" type="checkbox" name="debit_cards" value="1" wire:model.defer="debit_cards">
<span>{{ ctrans('texts.accept_debit_cards') }}</span>
</div>
</div>
@endif
@if($country == 'US')
<div class="col-span-6 sm:col-span-4 {{ $country != 'US' ? 'hidden' : 'block' }}">
<label for="country" class="input-label">@lang('texts.ach')</label>
<div class="checkbox">
<input class="form-checkbox cursor-pointer mr-2" type="checkbox" name="ach" value="1" wire:model="ach">
<span>{{ ctrans('texts.enable_ach')}}</span>
</div>
</div>
@endif
<div class="col-span-6 sm:col-span-4">
<label for="country" class="input-label"></label>
<div class="checkbox">
<input class="form-checkbox cursor-pointer mr-2" type="checkbox" name="wepay_payment_tos_agree" value="1" wire:model.defer="wepay_payment_tos_agree">
<span>{!! ctrans('texts.wepay_payment_tos_agree', ['terms' => $terms, 'privacy_policy' => $privacy_policy]) !!}</span>
</div>
@error('wepay_payment_tos_agree')
<div class="validation validation-fail">
{{ $message }}
</div>
@enderror
</div>
<div class="col-span-6 sm:col-span-4">
<span><i>{{ ctrans('texts.standard_fees_apply')}}</i></span>
</div>
<div class="col-span-6 {{ $country != 'CA' ? 'hidden' : 'block' }}">
<table id="canadaFees" width="100%" class="min-w-full"
style="border: 1px solid black; margin-bottom: 40px; display: table;">
<tbody>
<tr style="border: solid 1px black">
<th colspan="2" style="text-align:center;padding: 4px">
Fees Disclosure Box
</th>
</tr>
<tr style="border: solid 1px black;vertical-align:top">
<td style="border-left: solid 1px black; padding: 8px">
<h4>Payment Card Type</h4>
(These are the most common domestically issued card types
and processing methods. They do not represent all the
possible fees and variations that are charged to the
merchants.)
</td>
<td style="padding: 8px">
<h4>Processing Method: Card Not Present</h4>
(Means that the card/device was not
electronically read. Generally, the card
information is manually key-entered, e.g. online
payment)
</td>
</tr>
<tr>
<td style="border-left: solid 1px black;padding-left:8px;padding-top:4px;">
Visa Consumer Credit
</td>
<td style="text-align:center">
2.9% + CA$0.30
</td>
</tr>
<tr>
<td style="border-left: solid 1px black;padding-left:8px;padding-top:4px;">
Visa Infinite
</td>
<td style="text-align:center">
2.9% + CA$0.30
</td>
</tr>
<tr>
<td style="border-left: solid 1px black;padding-left:8px;padding-top:4px;">
Visa Infinite Privilege
</td>
<td style="text-align:center">
2.9% + CA$0.30
</td>
</tr>
<tr>
<td style="border-left: solid 1px black;padding-left:8px;padding-top:4px;">
Visa Business
</td>
<td style="text-align:center">
2.9% + CA$0.30
</td>
</tr>
<tr>
<td style="border-left: solid 1px black;padding-left:8px;padding-top:4px;">
Visa Business Premium
</td>
<td style="text-align:center">
2.9% + CA$0.30
</td>
</tr>
<tr>
<td style="border-left: solid 1px black;padding-left:8px;padding-top:4px;">
Visa Corporate
</td>
<td style="text-align:center">
2.9% + CA$0.30
</td>
</tr>
<tr>
<td style="border-left: solid 1px black;padding-left:8px;padding-top:4px;">
Visa Prepaid
</td>
<td style="text-align:center">
2.9% + CA$0.30
</td>
</tr>
<tr>
<td style="border-left: solid 1px black;padding-left:8px;padding-top:4px;">
Visa Debit
</td>
<td style="text-align:center">
2.9% + CA$0.30
</td>
</tr>
<tr>
<td style="border-left: solid 1px black;padding-left:8px;padding-top:4px;">
MasterCard Consumer Credit
</td>
<td style="text-align:center">
2.9% + CA$0.30
</td>
</tr>
<tr>
<td style="border-left: solid 1px black;padding-left:8px;padding-top:4px;">
MasterCard World
</td>
<td style="text-align:center">
2.9% + CA$0.30
</td>
</tr>
<tr>
<td style="border-left: solid 1px black;padding-left:8px;padding-top:4px;">
MasterCard World Elite
</td>
<td style="text-align:center">
2.9% + CA$0.30
</td>
</tr>
<tr>
<td style="border-left: solid 1px black;padding-left:8px;padding-top:4px;">
MasterCard Business/Corporate
</td>
<td style="text-align:center">
2.9% + CA$0.30
</td>
</tr>
<tr>
<td style="border-left: solid 1px black;padding-left:8px;padding-top:4px;">
MasterCard Debit
</td>
<td style="text-align:center">
2.9% + CA$0.30
</td>
</tr>
<tr>
<td style="border-left: solid 1px black;padding-left:8px;padding-top:4px;">
MasterCard Prepaid
</td>
<td style="text-align:center">
2.9% + CA$0.30
</td>
</tr>
<tr>
<td style="border-left: solid 1px black;padding-left:8px;padding-top:4px;">
American Express
</td>
<td style="text-align:center">
2.9% + CA$0.30
</td>
</tr>
<tr style="border: solid 1px black;">
<th colspan="2" style="text-align:center;padding: 4px">
Other Fees Disclosure Box
</th>
</tr>
<tr style="border: solid 1px black;">
<td style="border-left: solid 1px black;padding-left:8px;padding-top:4px;">
Chargeback
</td>
<td style="text-align:center">
CA$15.00
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
<button class="button button-primary bg-primary">{{ $saved }}</button>
</div>
</div>
</form>
</div>

View File

@ -80,6 +80,7 @@ Route::group(['middleware' => ['auth:contact', 'locale', 'check_client_existence
Route::post('upload', 'ClientPortal\UploadController')->name('upload.store'); Route::post('upload', 'ClientPortal\UploadController')->name('upload.store');
Route::get('logout', 'Auth\ContactLoginController@logout')->name('logout'); Route::get('logout', 'Auth\ContactLoginController@logout')->name('logout');
}); });
Route::get('client/subscriptions/{subscription}/purchase', 'ClientPortal\SubscriptionPurchaseController@index')->name('client.subscription.purchase')->middleware('domain_db'); Route::get('client/subscriptions/{subscription}/purchase', 'ClientPortal\SubscriptionPurchaseController@index')->name('client.subscription.purchase')->middleware('domain_db');

View File

@ -20,6 +20,9 @@ Route::post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail'
Route::get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->middleware(['domain_db','email_db'])->name('password.reset'); Route::get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->middleware(['domain_db','email_db'])->name('password.reset');
Route::post('password/reset', 'Auth\ResetPasswordController@reset')->middleware('email_db')->name('password.update'); Route::post('password/reset', 'Auth\ResetPasswordController@reset')->middleware('email_db')->name('password.update');
Route::get('wepay/signup/{token}', 'WePayController@signup')->name('wepay.signup');
Route::get('wepay/finished', 'WePayController@finished')->name('wepay.finished');
/* /*
* Social authentication * Social authentication
*/ */

View File

@ -84,7 +84,7 @@ class CompanyLedgerTest extends TestCase
$settings = CompanySettings::defaults(); $settings = CompanySettings::defaults();
$settings->company_logo = 'https://www.invoiceninja.com/wp-content/uploads/2019/01/InvoiceNinja-Logo-Round-300x300.png'; $settings->company_logo = asset('images/new_logo.png');
$settings->website = 'www.invoiceninja.com'; $settings->website = 'www.invoiceninja.com';
$settings->address1 = 'Address 1'; $settings->address1 = 'Address 1';
$settings->address2 = 'Address 2'; $settings->address2 = 'Address 2';

View File

@ -167,7 +167,7 @@ trait MockAccountData
$settings = CompanySettings::defaults(); $settings = CompanySettings::defaults();
$settings->company_logo = 'https://www.invoiceninja.com/wp-content/uploads/2019/01/InvoiceNinja-Logo-Round-300x300.png'; $settings->company_logo = asset('images/new_logo.png');
$settings->website = 'www.invoiceninja.com'; $settings->website = 'www.invoiceninja.com';
$settings->address1 = 'Address 1'; $settings->address1 = 'Address 1';
$settings->address2 = 'Address 2'; $settings->address2 = 'Address 2';
@ -199,7 +199,7 @@ trait MockAccountData
} }
$user->password = Hash::make('ALongAndBriliantPassword'); $user->password = Hash::make('ALongAndBriliantPassword');
$user_id = $user->id; $user_id = $user->id;
$this->user = $user; $this->user = $user;
@ -292,7 +292,7 @@ trait MockAccountData
$this->task->status_id = TaskStatus::where('company_id', $this->company->id)->first()->id; $this->task->status_id = TaskStatus::where('company_id', $this->company->id)->first()->id;
$this->task->save(); $this->task->save();
$this->expense_category = ExpenseCategory::factory()->create([ $this->expense_category = ExpenseCategory::factory()->create([
'user_id' => $user_id, 'user_id' => $user_id,
'company_id' => $this->company->id, 'company_id' => $this->company->id,
@ -562,7 +562,7 @@ trait MockAccountData
$data[1]['fee_tax_rate3'] = 0; $data[1]['fee_tax_rate3'] = 0;
$data[1]['fee_cap'] = ''; $data[1]['fee_cap'] = '';
$data[1]['is_enabled'] = true; $data[1]['is_enabled'] = true;
$cg = new CompanyGateway; $cg = new CompanyGateway;
$cg->company_id = $this->company->id; $cg->company_id = $this->company->id;
$cg->user_id = $user_id; $cg->user_id = $user_id;

11
webpack.mix.js vendored
View File

@ -69,9 +69,18 @@ mix.js("resources/js/app.js", "public/js")
.js( .js(
"resources/js/clients/payments/braintree-credit-card.js", "resources/js/clients/payments/braintree-credit-card.js",
"public/js/clients/payments/braintree-credit-card.js" "public/js/clients/payments/braintree-credit-card.js"
).js( )
.js(
"resources/js/clients/payments/braintree-paypal.js", "resources/js/clients/payments/braintree-paypal.js",
"public/js/clients/payments/braintree-paypal.js" "public/js/clients/payments/braintree-paypal.js"
)
.js(
"resources/js/clients/payments/wepay-credit-card.js",
"public/js/clients/payments/wepay-credit-card.js"
)
.js(
"resources/js/clients/payment_methods/wepay-bank-account.js",
"public/js/clients/payment_methods/wepay-bank-account.js"
); );
mix.copyDirectory('node_modules/card-js/card-js.min.css', 'public/css/card-js.min.css'); mix.copyDirectory('node_modules/card-js/card-js.min.css', 'public/css/card-js.min.css');