1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-20 16:31:33 +02:00

Merge branch 'v5-develop' into db

This commit is contained in:
David Bomba 2021-04-24 23:28:02 +10:00 committed by GitHub
commit e7e298c917
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
71 changed files with 277103 additions and 276594 deletions

View File

@ -2,6 +2,10 @@
## [Unreleased (daily channel)](https://github.com/invoiceninja/invoiceninja/tree/v5-develop)
## Fixed:
- Fixes for e-mails, encoding & parsing invalid HTML
## [v5.1.50-release](https://github.com/invoiceninja/invoiceninja/releases/tag/v5.1.50-release)
## Fixed:
- Refactor of e-mail templates
- Client portal: Invoices & recurring invoices are now sorted by date (by default)

View File

@ -1 +1 @@
5.1.50
5.1.53

View File

@ -54,4 +54,22 @@ class EmailFailure
* @var string
*/
public $string_metric6 = '';
/**
* The counter
* set to 1.
*
* @var string
*/
public $int_metric1 = 1;
/**
* Company Key
* @var string
*/
public $string_metric7 = '';
public function __construct($string_metric7) {
$this->string_metric7 = $string_metric7;
}
}

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://opensource.org/licenses/AAL
*/
namespace App\DataMapper\Analytics;
class EmailSuccess
{
/**
* The type of Sample.
*
* Monotonically incrementing counter
*
* - counter
*
* @var string
*/
public $type = 'mixed_metric';
/**
* The name of the counter.
* @var string
*/
public $name = 'job.success.email';
/**
* The datetime of the counter measurement.
*
* date("Y-m-d H:i:s")
*
* @var DateTime
*/
public $datetime;
/**
* The Class failure name
* set to 0.
*
* @var string
*/
public $string_metric5 = '';
/**
* The exception string
* set to 0.
*
* @var string
*/
public $string_metric6 = '';
/**
* The counter
* set to 1.
*
* @var string
*/
public $int_metric1 = 1;
/**
* Company Key
* @var string
*/
public $string_metric7 = '';
public function __construct($string_metric7) {
$this->string_metric7 = $string_metric7;
}
}

View File

@ -1,55 +0,0 @@
<?php
namespace App\Events\ClientSubscription;
use App\Models\ClientSubscription;
use App\Models\Company;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class ClientSubscriptionWasCreated
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* @var ClientSubscription
*/
public $client_subscription;
/**
* @var Company
*/
public $company;
/**
* @var array
*/
public $event_vars;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(ClientSubscription $client_subscription, Company $company, array $event_vars)
{
$this->client_subscription = $client_subscription;
$this->company = $company;
$this->event_vars = $event_vars;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}

View File

@ -246,7 +246,7 @@ class PaymentController extends Controller
}
$payment_hash = new PaymentHash;
$payment_hash->hash = Str::random(128);
$payment_hash->hash = Str::random(32);
$payment_hash->data = $hash_data;
$payment_hash->fee_total = $fee_totals;
$payment_hash->fee_invoice_id = $first_invoice->id;

View File

@ -1,410 +0,0 @@
<?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://opensource.org/licenses/AAL
*/
namespace App\Http\Controllers;
use App\Events\ClientSubscription\ClientSubscriptionWasCreated;
use App\Factory\ClientSubscriptionFactory;
use App\Http\Requests\ClientSubscription\CreateClientSubscriptionRequest;
use App\Http\Requests\ClientSubscription\DestroyClientSubscriptionRequest;
use App\Http\Requests\ClientSubscription\EditClientSubscriptionRequest;
use App\Http\Requests\ClientSubscription\ShowClientSubscriptionRequest;
use App\Http\Requests\ClientSubscription\StoreClientSubscriptionRequest;
use App\Http\Requests\ClientSubscription\UpdateClientSubscriptionRequest;
use App\Models\ClientSubscription;
use App\Repositories\ClientSubscriptionRepository;
use App\Transformers\ClientSubscriptionTransformer;
use App\Utils\Ninja;
class ClientSubscriptionController extends BaseController
{
protected $entity_type = ClientSubscription::class;
protected $entity_transformer = ClientSubscriptionTransformer::class;
protected $client_subscription_repo;
public function __construct(ClientSubscriptionRepository $client_subscription_repo)
{
parent::__construct();
$this->client_subscription_repo = $client_subscription_repo;
}
/**
* Show the list of ClientSubscriptions.
*
* @return Response
*
* @OA\Get(
* path="/api/v1/client_subscriptions",
* operationId="getClientSubscriptions",
* tags={"client_subscriptions"},
* summary="Gets a list of client_subscriptions",
* description="Lists client_subscriptions.",
*
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),
* @OA\Response(
* response=200,
* description="A list of client_subscriptions",
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
* @OA\JsonContent(ref="#/components/schemas/ClientSubscription"),
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
* ),
* @OA\Response(
* response="default",
* description="Unexpected Error",
* @OA\JsonContent(ref="#/components/schemas/Error"),
* ),
* )
*/
public function index(): \Illuminate\Http\Response
{
$client_subscriptions = ClientSubscription::query()->company();
return $this->listResponse($client_subscriptions);
}
/**
* Show the form for creating a new resource.
*
* @param CreateClientSubscriptionRequest $request The request
*
* @return Response
*
*
* @OA\Get(
* path="/api/v1/client_subscriptions/create",
* operationId="getClientSubscriptionsCreate",
* tags={"client_subscriptions"},
* summary="Gets a new blank client_subscriptions object",
* description="Returns a blank object with default values",
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),
* @OA\Response(
* response=200,
* description="A blank client_subscriptions object",
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
* @OA\JsonContent(ref="#/components/schemas/ClientSubscription"),
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
*
* ),
* @OA\Response(
* response="default",
* description="Unexpected Error",
* @OA\JsonContent(ref="#/components/schemas/Error"),
* ),
* )
*/
public function create(CreateClientSubscriptionRequest $request): \Illuminate\Http\Response
{
$client_subscription = ClientSubscriptionFactory::create(auth()->user()->company()->id, auth()->user()->id);
return $this->itemResponse($client_subscription);
}
/**
* Store a newly created resource in storage.
*
* @param StoreClientSubscriptionRequest $request The request
*
* @return Response
*
*
* @OA\Post(
* path="/api/v1/client_subscriptions",
* operationId="storeClientSubscription",
* tags={"client_subscriptions"},
* summary="Adds a client_subscriptions",
* description="Adds an client_subscriptions to the system",
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),
* @OA\Response(
* response=200,
* description="Returns the saved client_subscriptions object",
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
* @OA\JsonContent(ref="#/components/schemas/ClientSubscription"),
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
*
* ),
* @OA\Response(
* response="default",
* description="Unexpected Error",
* @OA\JsonContent(ref="#/components/schemas/Error"),
* ),
* )
*/
public function store(StoreClientSubscriptionRequest $request): \Illuminate\Http\Response
{
$client_subscription = $this->client_subscription_repo->save($request->all(), ClientSubscriptionFactory::create(auth()->user()->company()->id, auth()->user()->id));
event(new ClientsubscriptionWasCreated($client_subscription, $client_subscription->company, Ninja::eventVars(auth()->user()->id)));
return $this->itemResponse($client_subscription);
}
/**
* Display the specified resource.
*
* @param ShowClientSubscriptionRequest $request The request
* @param Invoice $client_subscription The invoice
*
* @return Response
*
*
* @OA\Get(
* path="/api/v1/client_subscriptions/{id}",
* operationId="showClientSubscription",
* tags={"client_subscriptions"},
* summary="Shows an client_subscriptions",
* description="Displays an client_subscriptions by id",
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),
* @OA\Parameter(
* name="id",
* in="path",
* description="The ClientSubscription Hashed ID",
* example="D2J234DFA",
* required=true,
* @OA\Schema(
* type="string",
* format="string",
* ),
* ),
* @OA\Response(
* response=200,
* description="Returns the ClientSubscription object",
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
* @OA\JsonContent(ref="#/components/schemas/ClientSubscription"),
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
*
* ),
* @OA\Response(
* response="default",
* description="Unexpected Error",
* @OA\JsonContent(ref="#/components/schemas/Error"),
* ),
* )
*/
public function show(ShowClientSubscriptionRequest $request, ClientSubscription $client_subscription): \Illuminate\Http\Response
{
return $this->itemResponse($client_subscription);
}
/**
* Show the form for editing the specified resource.
*
* @param EditClientSubscriptionRequest $request The request
* @param Invoice $client_subscription The invoice
*
* @return Response
*
* @OA\Get(
* path="/api/v1/client_subscriptions/{id}/edit",
* operationId="editClientSubscription",
* tags={"client_subscriptions"},
* summary="Shows an client_subscriptions for editting",
* description="Displays an client_subscriptions by id",
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),
* @OA\Parameter(
* name="id",
* in="path",
* description="The ClientSubscription Hashed ID",
* example="D2J234DFA",
* required=true,
* @OA\Schema(
* type="string",
* format="string",
* ),
* ),
* @OA\Response(
* response=200,
* description="Returns the invoice object",
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
* @OA\JsonContent(ref="#/components/schemas/ClientSubscription"),
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
*
* ),
* @OA\Response(
* response="default",
* description="Unexpected Error",
* @OA\JsonContent(ref="#/components/schemas/Error"),
* ),
* )
*/
public function edit(EditClientSubscriptionRequest $request, ClientSubscription $client_subscription): \Illuminate\Http\Response
{
return $this->itemResponse($client_subscription);
}
/**
* Update the specified resource in storage.
*
* @param UpdateClientSubscriptionRequest $request The request
* @param ClientSubscription $client_subscription The invoice
*
* @return Response
*
*
* @OA\Put(
* path="/api/v1/client_subscriptions/{id}",
* operationId="updateClientSubscription",
* tags={"client_subscriptions"},
* summary="Updates an client_subscriptions",
* description="Handles the updating of an client_subscriptions by id",
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),
* @OA\Parameter(
* name="id",
* in="path",
* description="The ClientSubscription Hashed ID",
* example="D2J234DFA",
* required=true,
* @OA\Schema(
* type="string",
* format="string",
* ),
* ),
* @OA\Response(
* response=200,
* description="Returns the client_subscriptions object",
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
* @OA\JsonContent(ref="#/components/schemas/ClientSubscription"),
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
*
* ),
* @OA\Response(
* response="default",
* description="Unexpected Error",
* @OA\JsonContent(ref="#/components/schemas/Error"),
* ),
* )
*/
public function update(UpdateClientSubscriptionRequest $request, ClientSubscription $client_subscription)
{
if ($request->entityIsDeleted($client_subscription)) {
return $request->disallowUpdate();
}
$client_subscription = $this->client_subscription_repo->save($request->all(), $client_subscription);
return $this->itemResponse($client_subscription);
}
/**
* Remove the specified resource from storage.
*
* @param DestroyClientSubscriptionRequest $request
* @param ClientSubscription $invoice
*
* @return Response
*
* @throws \Exception
* @OA\Delete(
* path="/api/v1/client_subscriptions/{id}",
* operationId="deleteClientSubscription",
* tags={"client_subscriptions"},
* summary="Deletes a client_subscriptions",
* description="Handles the deletion of an client_subscriptions by id",
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),
* @OA\Parameter(
* name="id",
* in="path",
* description="The ClientSubscription Hashed ID",
* example="D2J234DFA",
* required=true,
* @OA\Schema(
* type="string",
* format="string",
* ),
* ),
* @OA\Response(
* response=200,
* description="Returns a HTTP status",
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
*
* ),
* @OA\Response(
* response="default",
* description="Unexpected Error",
* @OA\JsonContent(ref="#/components/schemas/Error"),
* ),
* )
*/
public function destroy(DestroyClientSubscriptionRequest $request, ClientSubscription $client_subscription): \Illuminate\Http\Response
{
$this->client_subscription_repo->delete($client_subscription);
return $this->itemResponse($client_subscription->fresh());
}
}

View File

@ -13,6 +13,8 @@ namespace App\Http\Controllers;
use App\Http\Requests\OneTimeToken\OneTimeRouterRequest;
use App\Http\Requests\OneTimeToken\OneTimeTokenRequest;
use App\Models\Company;
use App\Models\CompanyUser;
use App\Models\User;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
@ -23,7 +25,6 @@ class OneTimeTokenController extends BaseController
{
private $contexts = [
'stripe_connect_test' => 'https://connect.stripe.com/oauth/authorize?response_type=code&client_id=ca_J2FhIhcf9GT5BlWUNeQ1FhnZACaYZrOI&scope=read_write',
'stripe_connect' => 'https://connect.stripe.com/oauth/authorize?response_type=code&client_id=ca_J2Fh2tZfMlaaItUfbUwBBx4JPss8jCz9&scope=read_write'
];
@ -67,7 +68,6 @@ class OneTimeTokenController extends BaseController
*/
public function create(OneTimeTokenRequest $request)
{
$hash = Str::random(64);
$data = [
@ -76,10 +76,10 @@ class OneTimeTokenController extends BaseController
'context' => $request->input('context'),
];
Cache::put( $hash, $data, 3600 );
Cache::put( $hash, $data, 3600);
return response()->json(['hash' => $hash], 200);
}
public function router(OneTimeRouterRequest $request)
@ -89,9 +89,7 @@ class OneTimeTokenController extends BaseController
MultiDB::findAndSetDbByCompanyKey($data['company_key']);
// $user = User::findOrFail($data['user_id']);
// Auth::login($user, true);
// Cache::forget($request->input('hash'));
$this->sendTo($data['context']);

View File

@ -1,19 +0,0 @@
<?php
/**
* @OA\Schema(
* schema="ClientSubscription",
* type="object",
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="______"),
* @OA\Property(property="subscription_id", type="string", example="Opnel5aKBz", description="______"),
* @OA\Property(property="recurring_invoice_id", type="string", example="Opnel5aKBz", description="______"),
* @OA\Property(property="company_id", type="string", example="Opnel5aKBz", description="______"),
* @OA\Property(property="client_id", type="string", example="Opnel5aKBz", description="______"),
* @OA\Property(property="trial_started", type="string", example="10-10-2021", description="______"),
* @OA\Property(property="trial_ends", type="string", example="12-10-2021", description="______"),
* @OA\Property(property="is_deleted", type="boolean", example="true", description="______"),
* @OA\Property(property="archived_at", type="number", format="integer", example="1434342123", description="Timestamp"),
* @OA\Property(property="created_at", type="number", format="integer", example="134341234234", description="Timestamp"),
* @OA\Property(property="updated_at", type="number", format="integer", example="134341234234", description="Timestamp"),
* )
*/

View File

@ -13,14 +13,22 @@
namespace App\Http\Controllers;
use App\Http\Requests\Payments\PaymentWebhookRequest;
use App\Libraries\MultiDB;
use Auth;
class PaymentWebhookController extends Controller
{
public function __invoke(PaymentWebhookRequest $request, string $company_key, string $company_gateway_id)
{
MultiDB::findAndSetDbByCompanyKey($company_key);
$payment = $request->getPayment();
$client = is_null($payment) ? $request->getClient() : $payment->client;
// $contact= $client->primary_contact()->first();
// Auth::guard('contact')->login($contact, true);
return $request->getCompanyGateway()
->driver($client)
->processWebhookRequest($request, $payment);

View File

@ -276,9 +276,9 @@ class SetupController extends Controller
public function update()
{
if ( Ninja::isNinja() || !request()->has('secret') || (request()->input('secret') != config('ninja.update_secret')) ) {
// if( Ninja::isNinja() || !request()->has('secret') || (request()->input('secret') != config('ninja.update_secret')) )
if(!request()->has('secret') || (request()->input('secret') != config('ninja.update_secret')) )
return redirect('/');
}
$cacheCompiled = base_path('bootstrap/cache/compiled.php');
if (file_exists($cacheCompiled)) {
@ -299,7 +299,9 @@ class SetupController extends Controller
Artisan::call('migrate', ['--force' => true]);
Artisan::call('db:seed', ['--force' => true]);
return redirect('/?clear_cache=true');
$this->buildCache(true);
return redirect('/');
}
}

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://opensource.org/licenses/AAL
*/
namespace App\Http\Controllers;
use App\Factory\CompanyGatewayFactory;
use App\Http\Requests\StripeConnect\InitializeStripeConnectRequest;
use App\Libraries\MultiDB;
use App\Models\CompanyGateway;
use App\PaymentDrivers\Stripe\Connect\Account;
use Stripe\Exception\ApiErrorException;
class StripeConnectController extends BaseController
{
/**
* Initialize Stripe Connect flow.
*
* @param string $token One-time token
* @throws ApiErrorException
*/
public function initialize(InitializeStripeConnectRequest $request, string $token)
{
// Should we check if company has set country in the ap? Otherwise this will fail.
if(!is_array($request->getTokenContent()))
abort(400, 'Invalid token');
MultiDB::findAndSetDbByCompanyKey($request->getTokenContent()['company_key']);
$data = [
'type' => 'standard',
'email' => $request->getContact()->email,
'country' => $request->getCompany()->country()->iso_3166_2,
];
$exists = CompanyGateway::query()
->where('gateway_key', 'd14dd26a47cecc30fdd65700bfb67b34')
->where('company_id', $request->getCompany()->id)
->first();
if ($exists) {
return render('gateways.stripe.connect.existing');
}
$account = Account::create($data);
$link = Account::link($account->id, $token);
$company_gateway = CompanyGatewayFactory::create($request->getCompany()->id, $request->getContact()->id);
$company_gateway->fill([
'gateway_key' => 'd14dd26a47cecc30fdd65700bfb67b34',
'fees_and_limits' => [],
'config' => encrypt(json_encode(['account_id' => $account->id]))
]);
$company_gateway->save();
return redirect($link['url']);
}
public function completed()
{
return render('gateways.stripe.connect.completed');
}
}

View File

@ -1,40 +0,0 @@
<?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://opensource.org/licenses/AAL
*/
namespace App\Http\Requests\ClientSubscription;
use App\Http\Requests\Request;
use App\Models\ClientSubscription;
class CreateClientSubscriptionRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize(): bool
{
return auth()->user()->can('create', ClientSubscription::class);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//
];
}
}

View File

@ -1,40 +0,0 @@
<?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://opensource.org/licenses/AAL
*/
namespace App\Http\Requests\ClientSubscription;
use App\Http\Requests\Request;
use Illuminate\Foundation\Http\FormRequest;
class DestroyClientSubscriptionRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return auth()->user()->can('edit', $this->client_subscription);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//
];
}
}

View File

@ -1,40 +0,0 @@
<?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://opensource.org/licenses/AAL
*/
namespace App\Http\Requests\ClientSubscription;
use App\Http\Requests\Request;
use Illuminate\Foundation\Http\FormRequest;
class EditClientSubscriptionRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return auth()->user()->can('edit', $this->client_subscription);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//
];
}
}

View File

@ -1,40 +0,0 @@
<?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://opensource.org/licenses/AAL
*/
namespace App\Http\Requests\ClientSubscription;
use App\Http\Requests\Request;
use Illuminate\Foundation\Http\FormRequest;
class ShowClientSubscriptionRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize() : bool
{
return auth()->user()->can('view', $this->client_subscription);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//
];
}
}

View File

@ -1,38 +0,0 @@
<?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://opensource.org/licenses/AAL
*/
namespace App\Http\Requests\ClientSubscription;
use App\Http\Requests\Request;
use App\Models\ClientSubscription;
class StoreClientSubscriptionRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return auth()->user()->can('create', ClientSubscription::class);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [];
}
}

View File

@ -1,42 +0,0 @@
<?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://opensource.org/licenses/AAL
*/
namespace App\Http\Requests\ClientSubscription;
use App\Http\Requests\Request;
use App\Utils\Traits\ChecksEntityStatus;
class UpdateClientSubscriptionRequest extends Request
{
use ChecksEntityStatus;
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return auth()->user()->can('edit', $this->client_subscription);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//
];
}
}

View File

@ -0,0 +1,66 @@
<?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://opensource.org/licenses/AAL
*/
namespace App\Http\Requests\StripeConnect;
use App\Models\ClientContact;
use App\Models\Company;
use App\Models\User;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Cache;
class InitializeStripeConnectRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
return [
//
];
}
/**
* Resolve one-time token instance.
*
* @return mixed
*/
public function getTokenContent()
{
$data = Cache::get($this->token);
return $data;
}
public function getContact()
{
return User::findOrFail($this->getTokenContent()['user_id']);
}
public function getCompany()
{
return Company::where('company_key', $this->getTokenContent()['company_key'])->firstOrFail();
}
}

View File

@ -12,6 +12,7 @@
namespace App\Jobs\Mail;
use App\DataMapper\Analytics\EmailFailure;
use App\DataMapper\Analytics\EmailSuccess;
use App\Events\Invoice\InvoiceWasEmailedAndFailed;
use App\Events\Payment\PaymentWasEmailedAndFailed;
use App\Jobs\Mail\NinjaMailerObject;
@ -180,6 +181,8 @@ class NinjaMailerJob implements ShouldQueue
$message->getHeaders()->addTextHeader('GmailToken', $token);
});
LightLogs::create(new EmailSuccess($this->nmo->company_key->company_key))
->batch();
}
private function logMailError($errors, $recipient_object)
@ -198,7 +201,7 @@ class NinjaMailerJob implements ShouldQueue
nlog('mailer job failed');
nlog($exception->getMessage());
$job_failure = new EmailFailure();
$job_failure = new EmailFailure($this->nmo->company->company_key);
$job_failure->string_metric5 = get_parent_class($this);
$job_failure->string_metric6 = $exception->getMessage();

View File

@ -55,15 +55,17 @@ class TemplateEmail extends Mailable
$this->build_email->setBody(str_replace('$body', $this->build_email->getBody(), $this->client->getSetting('email_style_custom')));
}
$this->build_email->setBody(
DesignHelpers::parseMarkdownToHtml($this->build_email->getBody())
);
$settings = $this->client->getMergedSettings();
$this->build_email->setBody(
TemplateEngine::wrapElementsIntoTables('<div id="content-wrapper"></div>', $this->build_email->getBody(), $settings)
);
if ($this->build_email->getTemplate() !== 'custom') {
$this->build_email->setBody(
DesignHelpers::parseMarkdownToHtml($this->build_email->getBody())
);
$this->build_email->setBody(
TemplateEngine::wrapElementsIntoTables('<div id="content-wrapper"></div>', $this->build_email->getBody(), $settings)
);
}
$company = $this->client->company;

View File

@ -1,55 +0,0 @@
<?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://opensource.org/licenses/AAL
*/
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class ClientSubscription extends BaseModel
{
use HasFactory;
protected $fillable = [
// 'subscription_id',
// 'recurring_invoice_id',
// 'client_id',
// 'trial_started',
// 'trial_ends',
// 'is_deleted',
];
protected $casts = [
'is_deleted' => 'boolean',
'updated_at' => 'timestamp',
'created_at' => 'timestamp',
'deleted_at' => 'timestamp',
];
public function company(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Company::class);
}
public function recurring_invoice(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(RecurringInvoice::class);
}
public function client(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Client::class);
}
public function subscription(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(BillingSubscription::class);
}
}

View File

@ -269,15 +269,37 @@ class CompanyGateway extends BaseModel
*/
public function calcGatewayFeeLabel($amount, Client $client, $gateway_type_id = GatewayType::CREDIT_CARD) :string
{
$label = '';
$label = ' ';
$fee = $this->calcGatewayFee($amount, $gateway_type_id);
if ($fee > 0) {
$fee = Number::formatMoney(round($fee, 2), $client);
$label = ' - '.$fee.' '.ctrans('texts.fee');
// if ($fee > 0) {
// $fee = Number::formatMoney(round($fee, 2), $client);
// $label = ' - '.$fee.' '.ctrans('texts.fee');
// }
if($fee > 0) {
$fees_and_limits = $this->fees_and_limits->{$gateway_type_id};
if(strlen($fees_and_limits->fee_percent) >=1)
$label .= $fees_and_limits->fee_percent . '%';
if(strlen($fees_and_limits->fee_amount) >=1){
if(strlen($label) > 1) {
$label .= ' + ' . Number::formatMoney($fees_and_limits->fee_amount, $client);
}else {
$label .= Number::formatMoney($fees_and_limits->fee_amount, $client);
}
}
}
return $label;
}

View File

@ -1,72 +0,0 @@
<?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://opensource.org/licenses/AAL
*/
namespace App\Observers;
use App\Models\ClientSubscription;
class ClientSubscriptionObserver
{
/**
* Handle the client_subscription "created" event.
*
* @param ClientSubscription $client_subscription
* @return void
*/
public function created(ClientSubscription $client_subscription)
{
//
}
/**
* Handle the client_subscription "updated" event.
*
* @param ClientSubscription $client_subscription
* @return void
*/
public function updated(ClientSubscription $client_subscription)
{
//
}
/**
* Handle the client_subscription "deleted" event.
*
* @param ClientSubscription $client_subscription
* @return void
*/
public function deleted(ClientSubscription $client_subscription)
{
//
}
/**
* Handle the client_subscription "restored" event.
*
* @param ClientSubscription $client_subscription
* @return void
*/
public function restored(ClientSubscription $client_subscription)
{
//
}
/**
* Handle the client_subscription "force deleted" event.
*
* @param ClientSubscription $client_subscription
* @return void
*/
public function forceDeleted(ClientSubscription $client_subscription)
{
//
}
}

View File

@ -271,7 +271,7 @@ class BaseDriver extends AbstractPaymentDriver
$invoices->each(function ($invoice) use ($fee_total) {
if (collect($invoice->line_items)->contains('type_id', '3')) {
$invoice->service()->toggleFeesPaid()->save();
$invoice->service()->toggleFeesPaid()->deletePdf()->save();
$invoice->client->service()->updateBalance($fee_total)->save();
$invoice->ledger()->updateInvoiceBalance($fee_total, "Gateway fee adjustment for invoice {$invoice->number}");
}
@ -370,7 +370,13 @@ class BaseDriver extends AbstractPaymentDriver
$invoices = Invoice::whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->get();
$invoices->first()->invitations->each(function ($invitation) {
$invoices->each(function ($invoice){
$invoice->service()->deletePdf();
});
$invoices->first()->invitations->each(function ($invitation) use ($nmo){
if ($invitation->contact->send_email && $invitation->contact->email) {

View File

@ -141,7 +141,7 @@ class CreditCard
$this->checkout->payment_hash->data = array_merge((array)$this->checkout->payment_hash->data, ['checkout_payment_ref' => $payment]);
$this->checkout->payment_hash->save();
if ($this->checkout->client->currency()->code == 'EUR') {
if ($this->checkout->client->currency()->code == 'EUR' || $this->checkout->company_gateway->getConfigField('threeds')) {
$payment->{'3ds'} = ['enabled' => true];
$payment->{'success_url'} = route('payment_webhook', [

View File

@ -58,7 +58,7 @@ trait Utilities
private function processSuccessfulPayment(Payment $_payment)
{
if ($this->getParent()->payment_hash->data->store_card) {
$this->storePaymentMethod($_payment);
$this->storeLocalPaymentMethod($_payment);
}
$data = [
@ -118,7 +118,7 @@ trait Utilities
}
}
private function storePaymentMethod(Payment $response)
private function storeLocalPaymentMethod(Payment $response)
{
try {
$payment_meta = new stdClass;

View File

@ -91,7 +91,7 @@ class ACH
{
$this->stripe->init();
$bank_account = Customer::retrieveSource($request->customer, $request->source);
$bank_account = Customer::retrieveSource($request->customer, $request->source, $this->stripe->stripe_connect_auth);
try {
$bank_account->verify(['amounts' => request()->transactions]);
@ -121,6 +121,7 @@ class ACH
public function paymentResponse($request)
{
$this->stripe->init();
$source = ClientGatewayToken::query()
@ -152,7 +153,7 @@ class ACH
'currency' => $state['currency'],
'customer' => $state['customer'],
'source' => $state['source'],
]);
], $this->stripe->stripe_connect_auth);
$state = array_merge($state, $request->all());

View File

@ -62,9 +62,9 @@ class Charge
$this->stripe->init();
$local_stripe = new StripeClient(
$this->stripe->company_gateway->getConfigField('apiKey')
);
// $local_stripe = new StripeClient(
// $this->stripe->company_gateway->getConfigField('apiKey')
// );
$response = null;

View File

@ -0,0 +1,210 @@
<?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://opensource.org/licenses/AAL
*/
namespace App\PaymentDrivers\Stripe\Connect;
class Account
{
/**
* @throws \Stripe\Exception\ApiErrorException
*/
public static function create(array $payload): \Stripe\Account
{
$stripe = new \Stripe\StripeClient(
config('ninja.ninja_stripe_key')
);
return $stripe->accounts->create([
'type' => 'standard',
'country' => $payload['country'],
'email' => $payload['email'],
]);
}
/**
* @throws \Stripe\Exception\ApiErrorException
*/
public static function link(string $account_id, string $token): \Stripe\AccountLink
{
$stripe = new \Stripe\StripeClient(
config('ninja.ninja_stripe_key')
);
return $stripe->accountLinks->create([
'account' => $account_id,
'refresh_url' => route('stripe_connect.initialization', $token),
'return_url' => route('stripe_connect.return'),
'type' => 'account_onboarding',
]);
}
/*** 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,52 @@
<?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://opensource.org/licenses/AAL
*/
namespace App\PaymentDrivers;
use App\Factory\PaymentFactory;
use App\Http\Requests\Payments\PaymentWebhookRequest;
use App\Http\Requests\Request;
use App\Jobs\Util\SystemLogger;
use App\Models\ClientGatewayToken;
use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentHash;
use App\Models\SystemLog;
use App\PaymentDrivers\Stripe\ACH;
use App\PaymentDrivers\Stripe\Alipay;
use App\PaymentDrivers\Stripe\Charge;
use App\PaymentDrivers\Stripe\CreditCard;
use App\PaymentDrivers\Stripe\SOFORT;
use App\PaymentDrivers\Stripe\Utilities;
use App\Utils\Traits\MakesHash;
use Exception;
use Illuminate\Support\Carbon;
use Stripe\Customer;
use Stripe\Exception\ApiErrorException;
use Stripe\PaymentIntent;
use Stripe\PaymentMethod;
use Stripe\SetupIntent;
use Stripe\Stripe;
use Stripe\StripeClient;
class StripeConnectPaymentDriver extends StripePaymentDriver
{
public function __construct(CompanyGateway $company_gateway, Client $client = null, $invitation = false)
{
parent::__construct($company_gateway, $client, $invitation);
$this->stripe_connect = true;
}
}

View File

@ -55,6 +55,10 @@ class StripePaymentDriver extends BaseDriver
public $payment_method;
public $stripe_connect = false;
public $stripe_connect_auth = [];
public static $methods = [
GatewayType::CREDIT_CARD => CreditCard::class,
GatewayType::BANK_TRANSFER => ACH::class,
@ -72,11 +76,21 @@ class StripePaymentDriver extends BaseDriver
*/
public function init(): void
{
$this->stripe = new StripeClient(
$this->company_gateway->getConfigField('apiKey')
);
if($this->stripe_connect)
{
Stripe::setApiKey(config('ninja.ninja_stripe_key'));
$this->stripe_connect_auth = ["stripe_account" => $this->company_gateway->getConfigField('account_id')];
}
else
{
$this->stripe = new StripeClient(
$this->company_gateway->getConfigField('apiKey')
);
Stripe::setApiKey($this->company_gateway->getConfigField('apiKey'));
Stripe::setApiKey($this->company_gateway->getConfigField('apiKey'));
}
}
public function setPaymentMethod($payment_method_id)

View File

@ -1,31 +0,0 @@
<?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://opensource.org/licenses/AAL
*/
namespace App\Policies;
use App\Models\User;
/**
* Class ClientSubscriptionPolicy.
*/
class ClientSubscriptionPolicy extends EntityPolicy
{
/**
* Checks if the user has create permissions.
*
* @param User $user
* @return bool
*/
public function create(User $user) : bool
{
return $user->isAdmin() || $user->hasPermission('create_client_subscription') || $user->hasPermission('create_all');
}
}

View File

@ -14,7 +14,6 @@ namespace App\Providers;
use App\Models\Account;
use App\Models\Subscription;
use App\Models\Client;
use App\Models\ClientSubscription;
use App\Models\Company;
use App\Models\CompanyGateway;
use App\Models\CompanyToken;
@ -30,7 +29,6 @@ use App\Models\User;
use App\Observers\AccountObserver;
use App\Observers\SubscriptionObserver;
use App\Observers\ClientObserver;
use App\Observers\ClientSubscriptionObserver;
use App\Observers\CompanyGatewayObserver;
use App\Observers\CompanyObserver;
use App\Observers\CompanyTokenObserver;
@ -82,7 +80,6 @@ class AppServiceProvider extends ServiceProvider
Account::observe(AccountObserver::class);
Subscription::observe(SubscriptionObserver::class);
Client::observe(ClientObserver::class);
ClientSubscription::observe(ClientSubscriptionObserver::class);
Company::observe(CompanyObserver::class);
CompanyGateway::observe(CompanyGatewayObserver::class);
CompanyToken::observe(CompanyTokenObserver::class);

View File

@ -40,7 +40,6 @@ use App\Models\Webhook;
use App\Policies\ActivityPolicy;
use App\Policies\SubscriptionPolicy;
use App\Policies\ClientPolicy;
use App\Policies\ClientSubscriptionPolicy;
use App\Policies\CompanyGatewayPolicy;
use App\Policies\CompanyPolicy;
use App\Policies\CompanyTokenPolicy;

View File

@ -1,28 +0,0 @@
<?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://opensource.org/licenses/AAL
*/
namespace App\Repositories;
use App\Models\ClientSubscription;
class ClientSubscriptionRepository extends BaseRepository
{
public function save($data, ClientSubscription $client_subscription): ?ClientSubscription
{
$client_subscription
->fill($data)
->save();
return $client_subscription;
}
}

View File

@ -20,7 +20,6 @@ use App\Jobs\Util\SubscriptionWebhookHandler;
use App\Jobs\Util\SystemLogger;
use App\Models\Client;
use App\Models\ClientContact;
use App\Models\ClientSubscription;
use App\Models\Invoice;
use App\Models\PaymentHash;
use App\Models\Product;

View File

@ -1,78 +0,0 @@
<?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://opensource.org/licenses/AAL
*/
namespace App\Transformers;
use App\Models\BillingSubscription;
use App\Models\Client;
use App\Models\ClientSubscription;
use App\Models\RecurringInvoice;
use App\Utils\Traits\MakesHash;
class ClientSubscriptionTransformer extends EntityTransformer
{
use MakesHash;
/**
* @var array
*/
protected $defaultIncludes = [];
/**
* @var array
*/
protected $availableIncludes = [
'client',
'recurring_invoice',
'subscription',
];
public function transform(ClientSubscription $client_subscription): array
{
return [
'id' => $this->encodePrimaryKey($client_subscription->id),
'subscription_id' => $this->encodePrimaryKey($client_subscription->subscription_id),
'company_id' => $this->encodePrimaryKey($client_subscription->company_id),
'recurring_invoice_id' => $this->encodePrimaryKey($client_subscription->recurring_invoice_id),
'client_id' => $this->encodePrimaryKey($client_subscription->client_id),
'trial_started' => (string)$client_subscription->trial_started ?: '',
'trial_ends' => (string)$client_subscription->trial_ends ?: '',
'is_deleted' => (bool)$client_subscription->is_deleted,
'created_at' => (int)$client_subscription->created_at,
'updated_at' => (int)$client_subscription->updated_at,
'archived_at' => (int)$client_subscription->deleted_at,
];
}
public function includeClient(ClientSubscription $client_subscription): \League\Fractal\Resource\Item
{
$transformer = new ClientTransformer($this->serializer);
return $this->includeItem($client_subscription->client, $transformer, Client::class);
}
public function includeRecurringInvoice(ClientSubscription $client_subscription): \League\Fractal\Resource\Item
{
$transformer = new RecurringInvoiceTransformer($this->serializer);
return $this->includeItem($client_subscription->recurring_invoice, $transformer, RecurringInvoice::class);
}
public function includeSubscription(ClientSubscription $client_subscription): \League\Fractal\Resource\Item
{
$transformer = new BillingSubscriptionTransformer($this->serializer);
return $this->includeItem($client_subscription->subscription, $transformer, BillingSubscription::class);
}
}

View File

@ -15,7 +15,6 @@ use App\Models\Account;
use App\Models\Activity;
use App\Models\Subscription;
use App\Models\Client;
use App\Models\ClientSubscription;
use App\Models\Company;
use App\Models\CompanyGateway;
use App\Models\CompanyLedger;

View File

@ -52,6 +52,10 @@ class TemplateEngine
private $raw_body;
private $raw_subject;
/**
* @var array
*/
private $labels_and_values;
public function __construct($body, $subject, $entity, $entity_id, $template)
{
@ -165,17 +169,20 @@ class TemplateEngine
private function entityValues($contact)
{
$this->labels_and_values = (new HtmlEngine($this->entity_obj->invitations->first()))->generateLabelsAndValues();
$data = (new HtmlEngine($this->entity_obj->invitations->first()))->generateLabelsAndValues();
$this->body = strtr($this->body, $data['labels']);
$this->body = strtr($this->body, $data['values']);
$this->body = strtr($this->body, $this->labels_and_values['labels']);
$this->body = strtr($this->body, $this->labels_and_values['values']);
// $this->body = str_replace("\n", "<br>", $this->body);
$this->subject = strtr($this->subject, $data['labels']);
$this->subject = strtr($this->subject, $data['values']);
$this->subject = strtr($this->subject, $this->labels_and_values['labels']);
$this->subject = strtr($this->subject, $this->labels_and_values['values']);
$this->body = DesignHelpers::parseMarkdownToHtml($this->body);
$email_style = $this->settings_entity->getSetting('email_style');
if ($email_style !== 'custom') {
$this->body = DesignHelpers::parseMarkdownToHtml($this->body);
}
}
private function renderTemplate()
@ -192,6 +199,11 @@ class TemplateEngine
if ($email_style == 'custom') {
$wrapper = $this->settings_entity->getSetting('email_style_custom');
// In order to parse variables such as $signature in the body,
// we need to replace strings with the values from HTMLEngine.
$wrapper = strtr($wrapper, $this->labels_and_values['values']);
/*If no custom design exists, send back a blank!*/
if (strlen($wrapper) > 1) {
$wrapper = $this->renderView($wrapper, $data);
@ -206,7 +218,7 @@ class TemplateEngine
$data = [
'subject' => $this->subject,
'body' => self::wrapElementsIntoTables(strtr($wrapper, ['$body' => '']), $this->body, $this->entity_obj->client->getMergedSettings()),
'body' => $email_style == 'custom' ? $this->body : self::wrapElementsIntoTables(strtr('<div id="content-wrapper"></div>', ['$body' => '']), $this->body, $this->entity_obj->client->getMergedSettings()),
'wrapper' => $wrapper,
'raw_body' => $this->raw_body,
'raw_subject' => $this->raw_subject
@ -263,7 +275,7 @@ class TemplateEngine
public static function wrapElementsIntoTables(string $wrapper, string $body, $settings): ?string
{
$documents['wrapper'] = new \DOMDocument();
$documents['wrapper']->loadHTML($wrapper);
@$documents['wrapper']->loadHTML($wrapper);
$documents['master'] = new \DOMDocument();

View File

@ -37,11 +37,8 @@ trait AppSetup
{
$cached_tables = config('ninja.cached_tables');
if(request()->has('clear_cache'))
Artisan::call('optimize');
foreach ($cached_tables as $name => $class) {
if (request()->has('clear_cache') || !Cache::has($name) || $force) {
if (!Cache::has($name) || $force) {
// check that the table exists in case the migration is pending
if (!Schema::hasTable((new $class())->getTable())) {
@ -64,9 +61,8 @@ trait AppSetup
}
/*Build template cache*/
if (request()->has('clear_cache') || !Cache::has('templates')) {
$this->buildTemplates();
}
$this->buildTemplates();
}

26
composer.lock generated
View File

@ -51,16 +51,16 @@
},
{
"name": "aws/aws-sdk-php",
"version": "3.178.6",
"version": "3.178.7",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
"reference": "0aa83b522d5ffa794c02e7411af87a0e241a3082"
"reference": "9443aecbf56eb43e0c7a409494ae4c09f4cebf5f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/0aa83b522d5ffa794c02e7411af87a0e241a3082",
"reference": "0aa83b522d5ffa794c02e7411af87a0e241a3082",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/9443aecbf56eb43e0c7a409494ae4c09f4cebf5f",
"reference": "9443aecbf56eb43e0c7a409494ae4c09f4cebf5f",
"shasum": ""
},
"require": {
@ -135,9 +135,9 @@
"support": {
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
"issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.178.6"
"source": "https://github.com/aws/aws-sdk-php/tree/3.178.7"
},
"time": "2021-04-19T18:13:17+00:00"
"time": "2021-04-21T18:37:31+00:00"
},
{
"name": "bacon/bacon-qr-code",
@ -2026,16 +2026,16 @@
},
{
"name": "google/auth",
"version": "v1.15.0",
"version": "v1.15.1",
"source": {
"type": "git",
"url": "https://github.com/googleapis/google-auth-library-php.git",
"reference": "b346c07de6613e26443d7b4830e5e1933b830dc4"
"reference": "4e0c9367719df9703e96f5ad613041b87742471c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/b346c07de6613e26443d7b4830e5e1933b830dc4",
"reference": "b346c07de6613e26443d7b4830e5e1933b830dc4",
"url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/4e0c9367719df9703e96f5ad613041b87742471c",
"reference": "4e0c9367719df9703e96f5ad613041b87742471c",
"shasum": ""
},
"require": {
@ -2049,7 +2049,7 @@
"require-dev": {
"guzzlehttp/promises": "0.1.1|^1.3",
"kelvinmo/simplejwt": "^0.2.5|^0.5.1",
"phpseclib/phpseclib": "^2",
"phpseclib/phpseclib": "^2.0.31",
"phpunit/phpunit": "^4.8.36|^5.7",
"sebastian/comparator": ">=1.2.3",
"squizlabs/php_codesniffer": "^3.5"
@ -2077,9 +2077,9 @@
"support": {
"docs": "https://googleapis.github.io/google-auth-library-php/master/",
"issues": "https://github.com/googleapis/google-auth-library-php/issues",
"source": "https://github.com/googleapis/google-auth-library-php/tree/v1.15.0"
"source": "https://github.com/googleapis/google-auth-library-php/tree/v1.15.1"
},
"time": "2021-02-05T20:50:04+00:00"
"time": "2021-04-21T17:42:05+00:00"
},
{
"name": "graham-campbell/result-type",

View File

@ -14,8 +14,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', ''),
'app_version' => '5.1.50',
'app_tag' => '5.1.50-release',
'app_version' => '5.1.53',
'app_tag' => '5.1.53-release',
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', false),
@ -39,7 +39,7 @@ return [
'sentry_dsn' => env('SENTRY_LARAVEL_DSN', 'https://9b4e15e575214354a7d666489783904a@sentry.invoicing.co/6'),
'environment' => env('NINJA_ENVIRONMENT', 'selfhost'), // 'hosted', 'development', 'selfhost', 'reseller'
'preconfigured_install' => env('PRECONFIGURED_INSTALL',false),
'update_secret' => env('UPDATE_SECRET', false),
'update_secret' => env('UPDATE_SECRET', ''),
// Settings used by invoiceninja.com
'terms_of_service_url' => [
@ -147,4 +147,5 @@ return [
'webcron_secret' => env('WEBCRON_SECRET', false),
'disable_auto_update' => env('DISABLE_AUTO_UPDATE', false),
'invoiceninja_hosted_pdf_generation' => env('NINJA_HOSTED_PDF', false),
'ninja_stripe_key' => env('NINJA_STRIPE_KEY', null),
];

View File

@ -0,0 +1,47 @@
<?php
use App\Models\Gateway;
use App\Utils\Ninja;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class StripeConnectGateway extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Model::unguard();
$gateway = [
'id' => 56,
'name' => 'Stripe Connect',
'provider' => 'StripeConnect',
'sort_order' => 1,
'key' => 'd14dd26a47cecc30fdd65700bfb67b34',
'fields' => '{"account_id":""}'
];
Gateway::create($gateway);
if (Ninja::isNinja()) {
Gateway::where('id', 20)->update(['visible' => 0]);
Gateway::where('id', 56)->update(['visible' => 1]);
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@ -0,0 +1,56 @@
<?php
use App\Models\CompanyGateway;
use App\Models\Gateway;
use App\Utils\Traits\AppSetup;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddPropertyToCheckoutGatewayConfig extends Migration
{
use AppSetup;
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$gateway = Gateway::where('key', '3758e7f7c6f4cecf0f4f348b9a00f456')->first();
if($gateway)
{
$fields = json_decode($gateway->fields);
$fields->threeds = false;
$gateway->fields = json_encode($fields);
$gateway->save();
}
CompanyGateway::where('gateway_key', '3758e7f7c6f4cecf0f4f348b9a00f456')->each(function ($checkout){
$config = json_decode(decrypt($checkout->config));
$config->threeds = false;
$config = encrypt(json_encode($config));
$checkout->config = $config;
$checkout->save();
});
// $this->buildCache(true);
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
}
}

View File

@ -62,7 +62,7 @@ class PaymentLibrariesSeeder extends Seeder
['id' => 36, 'name' => 'AGMS', 'provider' => 'Agms', 'key' => '1b3c6f3ccfea4f5e7eadeae188cccd7f', 'fields' => '{"username":"","password":"","apiKey":"","accountNumber":""}'],
['id' => 37, 'name' => 'Barclays', 'provider' => 'BarclaysEpdq\Essential', 'key' => '7cba6ce5c125f9cb47ea8443ae671b68', 'fields' => '{"clientId":"","testMode":false,"language":"en_US","callbackMethod":"POST"}'],
['id' => 38, 'name' => 'Cardgate', 'provider' => 'Cardgate', 'key' => 'b98cfa5f750e16cee3524b7b7e78fbf6', 'fields' => '{"merchantId":"","language":"nl","apiKey":"","siteId":"","notifyUrl":"","returnUrl":"","cancelUrl":"","testMode":false}'],
['id' => 39, 'name' => 'Checkout.com', 'provider' => 'CheckoutCom', 'key' => '3758e7f7c6f4cecf0f4f348b9a00f456', 'fields' => '{"secretApiKey":"","publicApiKey":"","testMode":false}'],
['id' => 39, 'name' => 'Checkout.com', 'provider' => 'CheckoutCom', 'key' => '3758e7f7c6f4cecf0f4f348b9a00f456', 'fields' => '{"secretApiKey":"","publicApiKey":"","testMode":false,"threeds:false"}'],
['id' => 40, 'name' => 'Creditcall', 'provider' => 'Creditcall', 'key' => 'cbc7ef7c99d31ec05492fbcb37208263', 'fields' => '{"terminalId":"","transactionKey":"","testMode":false,"verifyCvv":true,"verifyAddress":false,"verifyZip":false}'],
['id' => 41, 'name' => 'Cybersource', 'provider' => 'Cybersource', 'key' => 'e186a98d3b079028a73390bdc11bdb82', 'fields' => '{"profileId":"","secretKey":"","accessKey":"","testMode":false}'],
['id' => 42, 'name' => 'ecoPayz', 'provider' => 'Ecopayz', 'key' => '761040aca40f685d1ab55e2084b30670', 'fields' => '{"merchantId":"","merchantPassword":"","merchantAccountNumber":"","testMode":false}'],

1124
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,36 +3,36 @@ const MANIFEST = 'flutter-app-manifest';
const TEMP = 'flutter-temp-cache';
const CACHE_NAME = 'flutter-app-cache';
const RESOURCES = {
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
"favicon.ico": "51636d3a390451561744c42188ccd628",
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
"version.json": "7069906ad6cc610c71d600bca7105f49",
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
"manifest.json": "ce1b79950eb917ea619a0a30da27c6a3",
"/": "23224b5e03519aaa87594403d54412cf",
"favicon.ico": "51636d3a390451561744c42188ccd628",
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "174c02fc4609e8fc4389f5d21f16a296",
"main.dart.js": "6c1bdcfdb9b47f1c487a57ad331504db",
"assets/NOTICES": "3bf0be7e0e4deca198e5f5c4800f9232",
"assets/fonts/MaterialIcons-Regular.otf": "1288c9e28052e028aba623321f7826ac",
"assets/AssetManifest.json": "659dcf9d1baf3aed3ab1b9c42112bf8f",
"assets/assets/images/google-icon.png": "0f118259ce403274f407f5e982e681c3",
"assets/assets/images/logo.png": "090f69e23311a4b6d851b3880ae52541",
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "174c02fc4609e8fc4389f5d21f16a296",
"assets/assets/images/payment_types/switch.png": "4fa11c45327f5fdc20205821b2cfd9cc",
"assets/assets/images/payment_types/maestro.png": "e533b92bfb50339fdbfa79e3dfe81f08",
"assets/assets/images/payment_types/other.png": "d936e11fa3884b8c9f1bd5c914be8629",
"assets/assets/images/payment_types/mastercard.png": "6f6cdc29ee2e22e06b1ac029cb52ef71",
"assets/assets/images/payment_types/carteblanche.png": "d936e11fa3884b8c9f1bd5c914be8629",
"assets/assets/images/payment_types/laser.png": "b4e6e93dd35517ac429301119ff05868",
"assets/assets/images/payment_types/unionpay.png": "7002f52004e0ab8cc0b7450b0208ccb2",
"assets/assets/images/payment_types/other.png": "d936e11fa3884b8c9f1bd5c914be8629",
"assets/assets/images/payment_types/switch.png": "4fa11c45327f5fdc20205821b2cfd9cc",
"assets/assets/images/payment_types/ach.png": "7433f0aff779dc98a649b7a2daf777cf",
"assets/assets/images/payment_types/jcb.png": "07e0942d16c5592118b72e74f2f7198c",
"assets/assets/images/payment_types/dinerscard.png": "06d85186ba858c18ab7c9caa42c92024",
"assets/assets/images/payment_types/mastercard.png": "6f6cdc29ee2e22e06b1ac029cb52ef71",
"assets/assets/images/payment_types/discover.png": "6c0a386a00307f87db7bea366cca35f5",
"assets/assets/images/payment_types/solo.png": "2030c3ccaccf5d5e87916a62f5b084d6",
"assets/assets/images/payment_types/visa.png": "3ddc4a4d25c946e8ad7e6998f30fd4e3",
"assets/assets/images/payment_types/amex.png": "c49a4247984b3732a4af50a3390aa978",
"assets/assets/images/payment_types/carteblanche.png": "d936e11fa3884b8c9f1bd5c914be8629",
"assets/assets/images/payment_types/paypal.png": "8e06c094c1871376dfea1da8088c29d1",
"assets/assets/images/payment_types/maestro.png": "e533b92bfb50339fdbfa79e3dfe81f08",
"assets/assets/images/payment_types/jcb.png": "07e0942d16c5592118b72e74f2f7198c",
"assets/assets/images/payment_types/amex.png": "c49a4247984b3732a4af50a3390aa978",
"assets/assets/images/payment_types/dinerscard.png": "06d85186ba858c18ab7c9caa42c92024",
"assets/assets/images/payment_types/solo.png": "2030c3ccaccf5d5e87916a62f5b084d6",
"assets/assets/images/payment_types/ach.png": "7433f0aff779dc98a649b7a2daf777cf",
"assets/assets/images/payment_types/discover.png": "6c0a386a00307f87db7bea366cca35f5",
"assets/assets/images/google-icon.png": "0f118259ce403274f407f5e982e681c3",
"assets/assets/images/logo.png": "090f69e23311a4b6d851b3880ae52541",
"assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f",
"main.dart.js": "e0db24c26bb4d601e2d1cbbe0390beae",
"version.json": "7069906ad6cc610c71d600bca7105f49"
"/": "23224b5e03519aaa87594403d54412cf"
};
// The application shell files that are downloaded before a service worker can

View File

@ -1,2 +1,2 @@
/*! For license information please see stripe-ach.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=3)}({3:function(e,t,n){e.exports=n("M5il")},M5il:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}(new(function(){function e(){var t=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),r(this,"setupStripe",(function(){return t.stripe=Stripe(t.key),t})),r(this,"getFormData",(function(){return{country:document.getElementById("country").value,currency:document.getElementById("currency").value,routing_number:document.getElementById("routing-number").value,account_number:document.getElementById("account-number").value,account_holder_name:document.getElementById("account-holder-name").value,account_holder_type:document.querySelector('input[name="account-holder-type"]:checked').value}})),r(this,"handleError",(function(e){document.getElementById("save-button").disabled=!1,document.querySelector("#save-button > svg").classList.add("hidden"),document.querySelector("#save-button > span").classList.remove("hidden"),t.errors.textContent="",t.errors.textContent=e,t.errors.hidden=!1})),r(this,"handleSuccess",(function(e){document.getElementById("gateway_response").value=JSON.stringify(e),document.getElementById("server_response").submit()})),r(this,"handleSubmit",(function(e){document.getElementById("save-button").disabled=!0,document.querySelector("#save-button > svg").classList.remove("hidden"),document.querySelector("#save-button > span").classList.add("hidden"),e.preventDefault(),t.errors.textContent="",t.errors.hidden=!0,t.stripe.createToken("bank_account",t.getFormData()).then((function(e){return e.hasOwnProperty("error")?t.handleError(e.error.message):t.handleSuccess(e)}))})),this.errors=document.getElementById("errors"),this.key=document.querySelector('meta[name="stripe-publishable-key"]').content}var t,o,u;return t=e,(o=[{key:"handle",value:function(){var e=this;document.getElementById("save-button").addEventListener("click",(function(t){return e.handleSubmit(t)}))}}])&&n(t.prototype,o),u&&n(t,u),e}())).setupStripe().handle()}});
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=3)}({3:function(e,t,n){e.exports=n("M5il")},M5il:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}(new(function(){function e(){var t=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),r(this,"setupStripe",(function(){return t.stripe=Stripe(t.key),t.stripe_connect&&(t.stripe.stripeAccount=t.stripe_connect),t})),r(this,"getFormData",(function(){return{country:document.getElementById("country").value,currency:document.getElementById("currency").value,routing_number:document.getElementById("routing-number").value,account_number:document.getElementById("account-number").value,account_holder_name:document.getElementById("account-holder-name").value,account_holder_type:document.querySelector('input[name="account-holder-type"]:checked').value}})),r(this,"handleError",(function(e){document.getElementById("save-button").disabled=!1,document.querySelector("#save-button > svg").classList.add("hidden"),document.querySelector("#save-button > span").classList.remove("hidden"),t.errors.textContent="",t.errors.textContent=e,t.errors.hidden=!1})),r(this,"handleSuccess",(function(e){document.getElementById("gateway_response").value=JSON.stringify(e),document.getElementById("server_response").submit()})),r(this,"handleSubmit",(function(e){document.getElementById("save-button").disabled=!0,document.querySelector("#save-button > svg").classList.remove("hidden"),document.querySelector("#save-button > span").classList.add("hidden"),e.preventDefault(),t.errors.textContent="",t.errors.hidden=!0,t.stripe.createToken("bank_account",t.getFormData()).then((function(e){return e.hasOwnProperty("error")?t.handleError(e.error.message):t.handleSuccess(e)}))})),this.errors=document.getElementById("errors"),this.key=document.querySelector('meta[name="stripe-publishable-key"]').content,this.stripe_connect=document.querySelector('meta[name="stripe-account-id"]').content}var t,o,u;return t=e,(o=[{key:"handle",value:function(){var e=this;document.getElementById("save-button").addEventListener("click",(function(t){return e.handleSubmit(t)}))}}])&&n(t.prototype,o),u&&n(t,u),e}())).setupStripe().handle()}});

View File

@ -1,2 +1,2 @@
/*! For license information please see stripe-alipay.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=7)}({"+keB":function(e,t){function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}new function e(t){var r=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),n(this,"setupStripe",(function(){return r.stripe=Stripe(r.key),r})),n(this,"handle",(function(){var e={type:"alipay",amount:document.querySelector('meta[name="amount"]').content,currency:document.querySelector('meta[name="currency"]').content,redirect:{return_url:document.querySelector('meta[name="return-url"]').content}};document.getElementById("pay-now").addEventListener("click",(function(t){document.getElementById("pay-now").disabled=!0,document.querySelector("#pay-now > svg").classList.add("hidden"),document.querySelector("#pay-now > span").classList.remove("hidden"),r.stripe.createSource(e).then((function(e){if(e.hasOwnProperty("source"))return window.location=e.source.redirect.url;document.getElementById("pay-now").disabled=!1,document.querySelector("#pay-now > svg").classList.remove("hidden"),document.querySelector("#pay-now > span").classList.add("hidden"),this.errors.textContent="",this.errors.textContent=e.error.message,this.errors.hidden=!1}))}))})),this.key=t,this.errors=document.getElementById("errors")}(document.querySelector('meta[name="stripe-publishable-key"]').content).setupStripe().handle()},7:function(e,t,n){e.exports=n("+keB")}});
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=7)}({"+keB":function(e,t){function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}new function e(t,r){var o=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),n(this,"setupStripe",(function(){return o.stripe=Stripe(o.key),o.stripeConnect&&(o.stripe.stripeAccount=o.stripeConnect),o})),n(this,"handle",(function(){var e={type:"alipay",amount:document.querySelector('meta[name="amount"]').content,currency:document.querySelector('meta[name="currency"]').content,redirect:{return_url:document.querySelector('meta[name="return-url"]').content}};document.getElementById("pay-now").addEventListener("click",(function(t){document.getElementById("pay-now").disabled=!0,document.querySelector("#pay-now > svg").classList.add("hidden"),document.querySelector("#pay-now > span").classList.remove("hidden"),o.stripe.createSource(e).then((function(e){if(e.hasOwnProperty("source"))return window.location=e.source.redirect.url;document.getElementById("pay-now").disabled=!1,document.querySelector("#pay-now > svg").classList.remove("hidden"),document.querySelector("#pay-now > span").classList.add("hidden"),this.errors.textContent="",this.errors.textContent=e.error.message,this.errors.hidden=!1}))}))})),this.key=t,this.stripeConnect=r,this.errors=document.getElementById("errors")}(document.querySelector('meta[name="stripe-publishable-key"]').content,document.querySelector('meta[name="stripe-account-id"]').content).setupStripe().handle()},7:function(e,t,n){e.exports=n("+keB")}});

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
/*! For license information please see stripe-sofort.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=6)}({6:function(e,t,n){e.exports=n("RFiP")},RFiP:function(e,t){function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}new function e(t){var r=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),n(this,"setupStripe",(function(){return r.stripe=Stripe(r.key),r})),n(this,"handle",(function(){var e={type:"sofort",amount:document.querySelector('meta[name="amount"]').content,currency:"eur",redirect:{return_url:document.querySelector('meta[name="return-url"]').content},sofort:{country:document.querySelector('meta[name="country"]').content}};document.getElementById("pay-now").addEventListener("click",(function(t){document.getElementById("pay-now").disabled=!0,document.querySelector("#pay-now > svg").classList.remove("hidden"),document.querySelector("#pay-now > span").classList.add("hidden"),r.stripe.createSource(e).then((function(e){if(e.hasOwnProperty("source"))return window.location=e.source.redirect.url;document.getElementById("pay-now").disabled=!1,document.querySelector("#pay-now > svg").classList.add("hidden"),document.querySelector("#pay-now > span").classList.remove("hidden"),this.errors.textContent="",this.errors.textContent=e.error.message,this.errors.hidden=!1,document.getElementById("pay-now").disabled=!1}))}))})),this.key=t,this.errors=document.getElementById("errors")}(document.querySelector('meta[name="stripe-publishable-key"]').content).setupStripe().handle()}});
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=6)}({6:function(e,t,n){e.exports=n("RFiP")},RFiP:function(e,t){function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var r=document.querySelector('meta[name="stripe-publishable-key"]').content,o=document.querySelector('meta[name="stripe-account-id"]').content;new function e(t,r){var u=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),n(this,"setupStripe",(function(){return u.stripe=Stripe(u.key),u.stripeConnect&&(u.stripe.stripeAccount=o),u})),n(this,"handle",(function(){var e={type:"sofort",amount:document.querySelector('meta[name="amount"]').content,currency:"eur",redirect:{return_url:document.querySelector('meta[name="return-url"]').content},sofort:{country:document.querySelector('meta[name="country"]').content}};document.getElementById("pay-now").addEventListener("click",(function(t){document.getElementById("pay-now").disabled=!0,document.querySelector("#pay-now > svg").classList.remove("hidden"),document.querySelector("#pay-now > span").classList.add("hidden"),u.stripe.createSource(e).then((function(e){if(e.hasOwnProperty("source"))return window.location=e.source.redirect.url;document.getElementById("pay-now").disabled=!1,document.querySelector("#pay-now > svg").classList.add("hidden"),document.querySelector("#pay-now > span").classList.remove("hidden"),this.errors.textContent="",this.errors.textContent=e.error.message,this.errors.hidden=!1,document.getElementById("pay-now").disabled=!1}))}))})),this.key=t,this.errors=document.getElementById("errors"),this.stripeConnect=r}(r,o).setupStripe().handle()}});

181342
public/main.dart.js vendored

File diff suppressed because one or more lines are too long

181962
public/main.foss.dart.js vendored

File diff suppressed because one or more lines are too long

187261
public/main.wasm.dart.js vendored

File diff suppressed because one or more lines are too long

View File

@ -8,10 +8,10 @@
"/js/clients/payments/authorize-credit-card-payment.js": "/js/clients/payments/authorize-credit-card-payment.js?id=a376eff2227da398b0ba",
"/js/clients/payments/card-js.min.js": "/js/clients/payments/card-js.min.js?id=5469146cd629ea1b5c20",
"/js/clients/payments/checkout-credit-card.js": "/js/clients/payments/checkout-credit-card.js?id=98e406fa8e4db0e93427",
"/js/clients/payments/stripe-ach.js": "/js/clients/payments/stripe-ach.js?id=c4012ad90f17d60432ad",
"/js/clients/payments/stripe-alipay.js": "/js/clients/payments/stripe-alipay.js?id=6dbe9316b98deea55421",
"/js/clients/payments/stripe-credit-card.js": "/js/clients/payments/stripe-credit-card.js?id=c37c3892d35c50d82521",
"/js/clients/payments/stripe-sofort.js": "/js/clients/payments/stripe-sofort.js?id=9b9fd56d655ad238f149",
"/js/clients/payments/stripe-ach.js": "/js/clients/payments/stripe-ach.js?id=76d8ba6a814b3015e359",
"/js/clients/payments/stripe-alipay.js": "/js/clients/payments/stripe-alipay.js?id=7a4ce306366be98be5f7",
"/js/clients/payments/stripe-credit-card.js": "/js/clients/payments/stripe-credit-card.js?id=2c828298b04fe30a4fe7",
"/js/clients/payments/stripe-sofort.js": "/js/clients/payments/stripe-sofort.js?id=282f5d57f1c1efe8f896",
"/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/shared/multiple-downloads.js": "/js/clients/shared/multiple-downloads.js?id=5c35d28cf0a3286e7c45",

View File

@ -14,11 +14,17 @@ class AuthorizeACH {
this.key = document.querySelector(
'meta[name="stripe-publishable-key"]'
).content;
this.stripe_connect = document.querySelector(
'meta[name="stripe-account-id"]'
).content;
}
setupStripe = () => {
this.stripe = Stripe(this.key);
if(this.stripe_connect)
this.stripe.stripeAccount = this.stripe_connect;
return this;
};

View File

@ -9,14 +9,19 @@
*/
class ProcessAlipay {
constructor(key) {
constructor(key, stripeConnect) {
this.key = key;
this.stripeConnect = stripeConnect;
this.errors = document.getElementById('errors');
}
setupStripe = () => {
this.stripe = Stripe(this.key);
if(this.stripeConnect)
this.stripe.stripeAccount = this.stripeConnect;
return this;
};
@ -57,4 +62,8 @@ const publishableKey = document.querySelector(
'meta[name="stripe-publishable-key"]'
).content;
new ProcessAlipay(publishableKey).setupStripe().handle();
const stripeConnect = document.querySelector(
'meta[name="stripe-account-id"]'
).content;
new ProcessAlipay(publishableKey, stripeConnect).setupStripe().handle();

View File

@ -9,14 +9,19 @@
*/
class StripeCreditCard {
constructor(key, secret, onlyAuthorization) {
constructor(key, secret, onlyAuthorization, stripeConnect) {
this.key = key;
this.secret = secret;
this.onlyAuthorization = onlyAuthorization;
this.stripeConnect = stripeConnect;
}
setupStripe() {
this.stripe = Stripe(this.key);
if(this.stripeConnect)
this.stripe.stripeAccount = this.stripeConnect;
this.elements = this.stripe.elements();
return this;
@ -201,4 +206,7 @@ const secret =
const onlyAuthorization =
document.querySelector('meta[name="only-authorization"]').content ?? '';
new StripeCreditCard(publishableKey, secret, onlyAuthorization).handle();
const stripeConnect =
document.querySelector('meta[name="stripe-account-id"]').content;
new StripeCreditCard(publishableKey, secret, onlyAuthorization, stripeConnect).handle();

View File

@ -9,14 +9,18 @@
*/
class ProcessSOFORT {
constructor(key) {
constructor(key, stripeConnect) {
this.key = key;
this.errors = document.getElementById('errors');
this.stripeConnect = stripeConnect;
}
setupStripe = () => {
this.stripe = Stripe(this.key);
if(this.stripeConnect)
this.stripe.stripeAccount = stripeConnect;
return this;
};
@ -62,4 +66,7 @@ const publishableKey = document.querySelector(
'meta[name="stripe-publishable-key"]'
).content;
new ProcessSOFORT(publishableKey).setupStripe().handle();
const stripeConnect =
document.querySelector('meta[name="stripe-account-id"]').content;
new ProcessSOFORT(publishableKey, stripeConnect).setupStripe().handle();

View File

@ -1775,6 +1775,7 @@ $LANG = array(
'lang_Chinese - Taiwan' => 'Chinese - Taiwan',
'lang_Serbian' => 'Serbian',
'lang_Bulgarian' => 'Bulgarian',
'lang_Russian' => 'Russian',
// Industries
'industry_Accounting & Legal' => 'Accounting & Legal',

View File

@ -224,11 +224,15 @@
<div class="u-col u-col-100" style="max-width: 320px;min-width: 500px;display: table-cell;vertical-align: top;">
<div style="width: 100% !important;">
<!--[if (!mso)&(!IE)]><!--><div style="padding: 11px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;"><!--<![endif]-->
<div id="content-wrapper">
<div class="content-contrast-color">
@yield('greeting')
</div>
<div id="content-wrapper">
{{ $slot }}
</div>
<div class="content-contrast-color">
@yield('signature')
@yield('footer')
</div>

View File

@ -8,47 +8,24 @@
<title>Invoice Ninja</title>
</head>
<body>
<table role="presentation" cellpadding="0" cellspacing="0" width="100%">
<div id="content-wrapper">
{!! $body !!}
</div>
@if($signature)
<tr>
<td style="font-family: Arial, sans-serif, 'Open Sans'">
<table cellpadding="0" cellspacing="0" width="100%">
<tr>
<td>
<table cellpadding="0" cellspacing="0" width="100%">
<tr>
<td id="email-content">
{!! $body !!}
</td>
</tr>
</table>
</td>
</tr>
@if($signature)
<tr>
<td>
<p>{!! $signature !!}</p>
</td>
</tr>
@endif
<tr>
@isset($whitelabel)
@if(!$whitelabel)
<td>
<p>
<a href="https://invoiceninja.com" target="_blank">
{{ __('texts.ninja_email_footer', ['site' => 'Invoice Ninja']) }}
</a>
</p>
</td>
@endif
@endif
</tr>
</table>
<td>
<p>{!! $signature !!}</p>
</td>
</tr>
</table>
</body>
</html>
@endif
@isset($whitelabel)
@if(!$whitelabel)
<p>
<a href="https://invoiceninja.com" target="_blank">
{{ __('texts.ninja_email_footer', ['site' => 'Invoice Ninja']) }}
</a>
</p>
@endif
@endisset

View File

@ -2,6 +2,7 @@
@section('gateway_head')
<meta name="stripe-publishable-key" content="{{ $gateway->company_gateway->getPublishableKey() }}">
<meta name="stripe-account-id" content="{{ $gateway->company_gateway->getConfigField('account_id') }}">
@endsection
@section('gateway_content')

View File

@ -2,6 +2,7 @@
@section('gateway_head')
<meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}">
<meta name="stripe-account-id" content="{{ $gateway->company_gateway->getConfigField('account_id') }}">
<meta name="return-url" content="{{ $return_url }}">
<meta name="currency" content="{{ $currency }}">
<meta name="amount" content="{{ $stripe_amount }}">

View File

@ -0,0 +1,13 @@
@extends('portal.ninja2020.layout.clean')
@section('meta_title', ctrans('texts.success'))
@section('body')
<div class="flex flex-col justify-center items-center mt-10">
<div class="mb-4">
<svg height="60" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 468 222.5" xml:space="preserve"><style>.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#635bff}</style><path class="st0" d="M414 113.4c0-25.6-12.4-45.8-36.1-45.8-23.8 0-38.2 20.2-38.2 45.6 0 30.1 17 45.3 41.4 45.3 11.9 0 20.9-2.7 27.7-6.5v-20c-6.8 3.4-14.6 5.5-24.5 5.5-9.7 0-18.3-3.4-19.4-15.2h48.9c0-1.3.2-6.5.2-8.9zm-49.4-9.5c0-11.3 6.9-16 13.2-16 6.1 0 12.6 4.7 12.6 16h-25.8zM301.1 67.6c-9.8 0-16.1 4.6-19.6 7.8l-1.3-6.2h-22v116.6l25-5.3.1-28.3c3.6 2.6 8.9 6.3 17.7 6.3 17.9 0 34.2-14.4 34.2-46.1-.1-29-16.6-44.8-34.1-44.8zm-6 68.9c-5.9 0-9.4-2.1-11.8-4.7l-.1-37.1c2.6-2.9 6.2-4.9 11.9-4.9 9.1 0 15.4 10.2 15.4 23.3 0 13.4-6.2 23.4-15.4 23.4zM223.8 61.7l25.1-5.4V36l-25.1 5.3zM223.8 69.3h25.1v87.5h-25.1zM196.9 76.7l-1.6-7.4h-21.6v87.5h25V97.5c5.9-7.7 15.9-6.3 19-5.2v-23c-3.2-1.2-14.9-3.4-20.8 7.4zM146.9 47.6l-24.4 5.2-.1 80.1c0 14.8 11.1 25.7 25.9 25.7 8.2 0 14.2-1.5 17.5-3.3V135c-3.2 1.3-19 5.9-19-8.9V90.6h19V69.3h-19l.1-21.7zM79.3 94.7c0-3.9 3.2-5.4 8.5-5.4 7.6 0 17.2 2.3 24.8 6.4V72.2c-8.3-3.3-16.5-4.6-24.8-4.6C67.5 67.6 54 78.2 54 95.9c0 27.6 38 23.2 38 35.1 0 4.6-4 6.1-9.6 6.1-8.3 0-18.9-3.4-27.3-8v23.8c9.3 4 18.7 5.7 27.3 5.7 20.8 0 35.1-10.3 35.1-28.2-.1-29.8-38.2-24.5-38.2-35.7z"/></svg>
</div>
<p>Connecting your account using Stripe has been successfully completed.</p>
<span>Click <a class="font-semibold hover:underline" href="{{ url('/#/settings/company_gateways') }}">here</a> to continue.</span>
</div>
@endsection

View File

@ -0,0 +1,13 @@
@extends('portal.ninja2020.layout.clean')
@section('meta_title', ctrans('texts.success'))
@section('body')
<div class="flex flex-col justify-center items-center mt-10">
<div class="mb-4">
<svg height="60" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 468 222.5" xml:space="preserve"><style>.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#635bff}</style><path class="st0" d="M414 113.4c0-25.6-12.4-45.8-36.1-45.8-23.8 0-38.2 20.2-38.2 45.6 0 30.1 17 45.3 41.4 45.3 11.9 0 20.9-2.7 27.7-6.5v-20c-6.8 3.4-14.6 5.5-24.5 5.5-9.7 0-18.3-3.4-19.4-15.2h48.9c0-1.3.2-6.5.2-8.9zm-49.4-9.5c0-11.3 6.9-16 13.2-16 6.1 0 12.6 4.7 12.6 16h-25.8zM301.1 67.6c-9.8 0-16.1 4.6-19.6 7.8l-1.3-6.2h-22v116.6l25-5.3.1-28.3c3.6 2.6 8.9 6.3 17.7 6.3 17.9 0 34.2-14.4 34.2-46.1-.1-29-16.6-44.8-34.1-44.8zm-6 68.9c-5.9 0-9.4-2.1-11.8-4.7l-.1-37.1c2.6-2.9 6.2-4.9 11.9-4.9 9.1 0 15.4 10.2 15.4 23.3 0 13.4-6.2 23.4-15.4 23.4zM223.8 61.7l25.1-5.4V36l-25.1 5.3zM223.8 69.3h25.1v87.5h-25.1zM196.9 76.7l-1.6-7.4h-21.6v87.5h25V97.5c5.9-7.7 15.9-6.3 19-5.2v-23c-3.2-1.2-14.9-3.4-20.8 7.4zM146.9 47.6l-24.4 5.2-.1 80.1c0 14.8 11.1 25.7 25.9 25.7 8.2 0 14.2-1.5 17.5-3.3V135c-3.2 1.3-19 5.9-19-8.9V90.6h19V69.3h-19l.1-21.7zM79.3 94.7c0-3.9 3.2-5.4 8.5-5.4 7.6 0 17.2 2.3 24.8 6.4V72.2c-8.3-3.3-16.5-4.6-24.8-4.6C67.5 67.6 54 78.2 54 95.9c0 27.6 38 23.2 38 35.1 0 4.6-4 6.1-9.6 6.1-8.3 0-18.9-3.4-27.3-8v23.8c9.3 4 18.7 5.7 27.3 5.7 20.8 0 35.1-10.3 35.1-28.2-.1-29.8-38.2-24.5-38.2-35.7z"/></svg>
</div>
<p>You have already configured a Stripe Connect account.</p>
<span>Click <a class="font-semibold hover:underline" href="{{ url('/#/settings/company_gateways') }}">here</a> to continue.</span>
</div>
@endsection

View File

@ -2,6 +2,7 @@
@section('gateway_head')
<meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}">
<meta name="stripe-account-id" content="{{ $gateway->company_gateway->getConfigField('account_id') }}">
<meta name="stripe-secret" content="{{ $intent->client_secret }}">
<meta name="only-authorization" content="true">
<meta name="stripe-token" content="">

View File

@ -2,6 +2,7 @@
@section('gateway_head')
<meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}">
<meta name="stripe-account-id" content="{{ $gateway->company_gateway->getConfigField('account_id') }}">
<meta name="stripe-secret" content="{{ $intent->client_secret }}">
<meta name="only-authorization" content="">
@endsection

View File

@ -2,6 +2,7 @@
@section('gateway_head')
<meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}">
<meta name="stripe-account-id" content="{{ $gateway->company_gateway->getConfigField('account_id') }}">
<meta name="return-url" content="{{ $return_url }}">
<meta name="amount" content="{{ $stripe_amount }}">
<meta name="country" content="{{ $country }}">

View File

@ -182,14 +182,21 @@ Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'a
Route::resource('subscriptions', 'SubscriptionController');
Route::post('subscriptions/bulk', 'SubscriptionController@bulk')->name('subscriptions.bulk');
Route::resource('cliente_subscriptions', 'ClientSubscriptionController');
});
Route::match(['get', 'post'], 'payment_webhook/{company_key}/{company_gateway_id}', 'PaymentWebhookController')
->middleware(['guest', 'api_db'])
->middleware(['guest'])
->name('payment_webhook');
Route::post('api/v1/postmark_webhook', 'PostMarkController@webhook');
Route::get('token_hash_router', 'OneTimeTokenController@router');
Route::get('webcron', 'WebCronController@index');
Route::group(['middleware' => ['locale']], function () {
Route::get('stripe_connect/{token}', 'StripeConnectController@initialize')->name('stripe_connect.initialization');
Route::get('stripe_connect/completed', 'StripeConnectController@completed')->name('stripe_connect.return');
});
Route::fallback('BaseController@notFound');