Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses

This commit is contained in:
paulwer 2024-05-21 06:50:47 +02:00
commit befbdc399d
58 changed files with 185902 additions and 185148 deletions

View File

@ -52,6 +52,10 @@ class DbQuery extends GenericMixedMetric
public $string_metric7 = 'ip_address'; public $string_metric7 = 'ip_address';
public $string_metric8 = 'client_version';
public $string_metric9 = 'platform';
/** /**
* The counter * The counter
* set to 1. * set to 1.

View File

@ -32,7 +32,6 @@ use App\Models\BankIntegration;
use App\Models\BankTransaction; use App\Models\BankTransaction;
use App\Models\ExpenseCategory; use App\Models\ExpenseCategory;
use League\Fractal\Resource\Item; use League\Fractal\Resource\Item;
use App\DataMapper\EDoc\Schema\RO;
use App\Models\BankTransactionRule; use App\Models\BankTransactionRule;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use App\Transformers\ArraySerializer; use App\Transformers\ArraySerializer;
@ -42,6 +41,7 @@ use Illuminate\Database\Eloquent\Builder;
use League\Fractal\Serializer\JsonApiSerializer; use League\Fractal\Serializer\JsonApiSerializer;
use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Contracts\Container\BindingResolutionException;
use Invoiceninja\Einvoice\Decoder\Schema;
/** /**
* Class BaseController. * Class BaseController.
@ -890,7 +890,6 @@ class BaseController extends Controller
/** @phpstan-ignore-next-line **/ /** @phpstan-ignore-next-line **/
$query = $paginator->getCollection();// @phpstan-ignore-line $query = $paginator->getCollection();// @phpstan-ignore-line
$resource = new Collection($query, $transformer, $this->entity_type); $resource = new Collection($query, $transformer, $this->entity_type);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
} }
@ -998,8 +997,8 @@ class BaseController extends Controller
if(request()->has('einvoice')){ if(request()->has('einvoice')){
$ro = new RO(); $ro = new Schema();
$response_data['einvoice_schema'] = $ro(); $response_data['einvoice_schema'] = $ro('FACT1');
} }

View File

@ -73,7 +73,22 @@ class QueryLogging
$ip = $request->ip(); $ip = $request->ip();
} }
LightLogs::create(new DbQuery($request->method(), substr(urldecode($request->url()), 0, 180), $count, $time, $ip)) $client_version = $request->server('HTTP_USER_AGENT');
$platform = '';
if ($request->hasHeader('X-CLIENT-PLATFORM')) {
$platform = $request->header('X-CLIENT-PLATFORM');
}
elseif($request->hasHeader('X-React')){
$platform = 'react';
}
if ($request->hasHeader('X-CLIENT-VERSION'))
{
$client_version = $request->header('X-CLIENT-VERSION');
}
LightLogs::create(new DbQuery($request->method(), substr(urldecode($request->url()), 0, 180), $count, $time, $ip, $client_version, $platform))
->batch(); ->batch();
} }

View File

@ -18,6 +18,7 @@ use App\Http\ValidationRules\Company\ValidSubdomain;
use App\Http\ValidationRules\ValidSettingsRule; use App\Http\ValidationRules\ValidSettingsRule;
use App\Utils\Ninja; use App\Utils\Ninja;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use Invoiceninja\Einvoice\Models\FatturaPA\FatturaElettronica;
class UpdateCompanyRequest extends Request class UpdateCompanyRequest extends Request
{ {
@ -120,6 +121,11 @@ class UpdateCompanyRequest extends Request
$input['smtp_verify_peer'] == 'true' ? true : false; $input['smtp_verify_peer'] == 'true' ? true : false;
} }
// if(isset($input['e_invoice'])){
// nlog("am i set?");
// $r = FatturaElettronica::validate($input['e_invoice']);
// }
$this->replace($input); $this->replace($input);
} }

View File

@ -241,6 +241,32 @@ class CompanyImport implements ShouldQueue
CompanyGateway::class => [ CompanyGateway::class => [
'always_show_required_fields', 'always_show_required_fields',
] ]
],
'5.8.57' => [
Company::class => [
'einvoice',
'e_invoice',
],
Invoice::class => [
'einvoice',
'e_invoice',
],
Quote::class => [
'einvoice',
'e_invoice',
],
Credit::class => [
'einvoice',
'e_invoice',
],
PurchaseOrder::class => [
'einvoice',
'e_invoice',
],
Expense::class => [
'einvoice',
'e_invoice',
],
] ]
]; ];

View File

@ -0,0 +1,62 @@
<?php
namespace App\Jobs\EDocument;
use App\Models\Invoice;
use App\Models\PurchaseOrder;
use horstoeko\zugferd\ZugferdDocumentPdfBuilder;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class MergeEDocument implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
public $deleteWhenMissingModels = true;
public function __construct(private mixed $document, private string $pdf_file)
{
}
/**
* Execute the job.
*
* @return string
*/
public function handle(): string
{
$settings_entity = ($this->document instanceof PurchaseOrder) ? $this->document->vendor : $this->document->client;
$e_document_type = strlen($settings_entity->getSetting('e_invoice_type')) > 2 ? $settings_entity->getSetting('e_invoice_type') : "XInvoice_3_0";
if ($this->document instanceof Invoice){
switch ($e_document_type) {
case "EN16931":
case "XInvoice_3_0":
case "XInvoice_2_3":
case "XInvoice_2_2":
case "XInvoice_2_1":
case "XInvoice_2_0":
case "XInvoice_1_0":
case "XInvoice-Extended":
case "XInvoice-BasicWL":
case "XInvoice-Basic":
$xml = (new CreateEDocument($this->document, true))->handle();
return(new ZugferdDocumentPdfBuilder($xml, $this->pdf_file))->generateDocument()->downloadString("Invoice.pdf");
default:
return $this->pdf_file;
}
}
else{
return $this->pdf_file;
}
}
}

View File

@ -12,6 +12,7 @@
namespace App\Jobs\Entity; namespace App\Jobs\Entity;
use App\Exceptions\FilePermissionsFailure; use App\Exceptions\FilePermissionsFailure;
use App\Jobs\EDocument\MergeEDocument;
use App\Models\Credit; use App\Models\Credit;
use App\Models\CreditInvitation; use App\Models\CreditInvitation;
use App\Models\Invoice; use App\Models\Invoice;
@ -95,6 +96,9 @@ class CreateRawPdf
} }
/**
* @throws FilePermissionsFailure
*/
public function handle() public function handle()
{ {
/** Testing this override to improve PDF generation performance */ /** Testing this override to improve PDF generation performance */
@ -104,11 +108,15 @@ class CreateRawPdf
"{$this->entity_string}s" => [$this->entity], "{$this->entity_string}s" => [$this->entity],
]); ]);
$pdf = $ps->boot()->getPdf(); try {
nlog("pdf timer = ". $ps->execution_time); $pdf = $ps->boot()->getPdf();
} catch (\Exception) {
throw new FilePermissionsFailure('Unable to generate the raw PDF');
}
if ($this->entity_string == "invoice" && $this->entity->getSetting("merge_e_invoice_to_pdf")){
$pdf = (new MergeEDocument($this->entity, $pdf))->handle();
}
return $pdf; return $pdf;
throw new FilePermissionsFailure('Unable to generate the raw PDF');
} }
public function failed($e) public function failed($e)

View File

@ -136,8 +136,8 @@ class NinjaMailerJob implements ShouldQueue
$mailable = $this->nmo->mailable; $mailable = $this->nmo->mailable;
/** May need to re-build it here */ /** May need to re-build it here @todo explain why we need this? */
if (Ninja::isHosted() && method_exists($mailable, 'build')) { if (Ninja::isHosted() && method_exists($mailable, 'build') && $this->nmo->settings->email_style != "custom") {
$mailable->build(); $mailable->build();
} }

View File

@ -116,13 +116,17 @@ class EmailPayment implements ShouldQueue
$invoice->invitations->each(function ($invite) use ($email_builder) { $invoice->invitations->each(function ($invite) use ($email_builder) {
$cloned_mailable = unserialize(serialize($email_builder));
$nmo = new NinjaMailerObject(); $nmo = new NinjaMailerObject();
$nmo->mailable = new TemplateEmail($email_builder, $invite->contact, $invite); $nmo->mailable = new TemplateEmail($cloned_mailable, $invite->contact, $invite);
$nmo->to_user = $invite->contact; $nmo->to_user = $invite->contact;
$nmo->settings = $this->settings; $nmo->settings = $this->settings;
$nmo->company = $this->company; $nmo->company = $this->company;
$nmo->entity = $this->payment; $nmo->entity = $this->payment;
(new NinjaMailerJob($nmo))->handle(); (new NinjaMailerJob($nmo))->handle();
$nmo = null;
event(new PaymentWasEmailed($this->payment, $this->payment->company, $invite->contact, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new PaymentWasEmailed($this->payment, $this->payment->company, $invite->contact, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));

View File

@ -126,7 +126,7 @@ class ReminderJob implements ShouldQueue
} }
$reminder_template = $invoice->calculateTemplate('invoice'); $reminder_template = $invoice->calculateTemplate('invoice');
nrlog("reminder template = {$reminder_template}"); nrlog("#{$invoice->number} => reminder template = {$reminder_template}");
$invoice->service()->touchReminder($reminder_template)->save(); $invoice->service()->touchReminder($reminder_template)->save();
$fees = $this->calcLateFee($invoice, $reminder_template); $fees = $this->calcLateFee($invoice, $reminder_template);

View File

@ -134,10 +134,6 @@ class InvoiceEmailEngine extends BaseEmailEngine
$this->setAttachments([['file' => base64_encode($pdf), 'name' => $this->invoice->numberFormatter().'.pdf']]); $this->setAttachments([['file' => base64_encode($pdf), 'name' => $this->invoice->numberFormatter().'.pdf']]);
} }
// $hash = Str::uuid();
// $url = \Illuminate\Support\Facades\URL::temporarySignedRoute('protected_download', now()->addHour(), ['hash' => $hash]);
// Cache::put($hash, $url, now()->addHour());
//attach third party documents //attach third party documents
if ($this->client->getSetting('document_email_attachment') !== false && $this->invoice->company->account->hasFeature(Account::FEATURE_DOCUMENTS)) { if ($this->client->getSetting('document_email_attachment') !== false && $this->invoice->company->account->hasFeature(Account::FEATURE_DOCUMENTS)) {
if ($this->invoice->recurring_invoice()->exists()) { if ($this->invoice->recurring_invoice()->exists()) {

View File

@ -99,7 +99,6 @@ class PaymentEmailEngine extends BaseEmailEngine
->setViewLink('') ->setViewLink('')
->setViewText(''); ->setViewText('');
if ($this->client->getSetting('pdf_email_attachment') !== false && $this->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) { if ($this->client->getSetting('pdf_email_attachment') !== false && $this->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) {
$template_in_use = false; $template_in_use = false;

View File

@ -31,6 +31,7 @@ use Laracasts\Presenter\PresentableTrait;
* App\Models\Account * App\Models\Account
* *
* @property int $id * @property int $id
* @property int $email_quota
* @property string|null $plan * @property string|null $plan
* @property string|null $plan_term * @property string|null $plan_term
* @property string|null $plan_started * @property string|null $plan_started

View File

@ -380,6 +380,7 @@ class Company extends BaseModel
'smtp_encryption', 'smtp_encryption',
'smtp_local_domain', 'smtp_local_domain',
'smtp_verify_peer', 'smtp_verify_peer',
'e_invoice',
]; ];
protected $hidden = [ protected $hidden = [
@ -404,6 +405,7 @@ class Company extends BaseModel
'e_invoice_certificate_passphrase' => EncryptedCast::class, 'e_invoice_certificate_passphrase' => EncryptedCast::class,
'smtp_username' => 'encrypted', 'smtp_username' => 'encrypted',
'smtp_password' => 'encrypted', 'smtp_password' => 'encrypted',
'e_invoice' => 'object',
]; ];
protected $with = []; protected $with = [];

View File

@ -155,6 +155,7 @@ class CompanyGateway extends BaseModel
'b9886f9257f0c6ee7c302f1c74475f6c' => 321, //GoCardless 'b9886f9257f0c6ee7c302f1c74475f6c' => 321, //GoCardless
'hxd6gwg3ekb9tb3v9lptgx1mqyg69zu9' => 322, 'hxd6gwg3ekb9tb3v9lptgx1mqyg69zu9' => 322,
'80af24a6a691230bbec33e930ab40666' => 323, '80af24a6a691230bbec33e930ab40666' => 323,
'vpyfbmdrkqcicpkjqdusgjfluebftuva' => 324, //BTPay
]; ];
protected $touches = []; protected $touches = [];

View File

@ -28,6 +28,7 @@ use Laracasts\Presenter\PresentableTrait;
* App\Models\Credit * App\Models\Credit
* *
* @property int $id * @property int $id
* @property object|null $e_invoice
* @property int $client_id * @property int $client_id
* @property int $user_id * @property int $user_id
* @property int|null $assigned_user_id * @property int|null $assigned_user_id
@ -179,6 +180,7 @@ class Credit extends BaseModel
'created_at' => 'timestamp', 'created_at' => 'timestamp',
'deleted_at' => 'timestamp', 'deleted_at' => 'timestamp',
'is_amount_discount' => 'bool', 'is_amount_discount' => 'bool',
'e_invoice' => 'object',
]; ];

View File

@ -17,6 +17,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* App\Models\Expense * App\Models\Expense
* *
* @property int $id * @property int $id
* @property object|null $e_invoice
* @property int|null $created_at * @property int|null $created_at
* @property int|null $updated_at * @property int|null $updated_at
* @property int|null $deleted_at * @property int|null $deleted_at
@ -141,6 +142,7 @@ class Expense extends BaseModel
'updated_at' => 'timestamp', 'updated_at' => 'timestamp',
'created_at' => 'timestamp', 'created_at' => 'timestamp',
'deleted_at' => 'timestamp', 'deleted_at' => 'timestamp',
'e_invoice' => 'object',
]; ];
protected $touches = []; protected $touches = [];

View File

@ -32,6 +32,7 @@ use Laracasts\Presenter\PresentableTrait;
* App\Models\Invoice * App\Models\Invoice
* *
* @property int $id * @property int $id
* @property object|null $e_invoice
* @property int $client_id * @property int $client_id
* @property int $user_id * @property int $user_id
* @property int|null $assigned_user_id * @property int|null $assigned_user_id
@ -209,6 +210,7 @@ class Invoice extends BaseModel
'custom_surcharge_tax2' => 'bool', 'custom_surcharge_tax2' => 'bool',
'custom_surcharge_tax3' => 'bool', 'custom_surcharge_tax3' => 'bool',
'custom_surcharge_tax4' => 'bool', 'custom_surcharge_tax4' => 'bool',
'e_invoice' => 'object',
]; ];
protected $with = []; protected $with = [];

View File

@ -83,9 +83,9 @@ class CompanyPresenter extends EntityPresenter
]; ];
if (strlen($settings->company_logo) >= 1 && (strpos($settings->company_logo, 'http') !== false)) { if (strlen($settings->company_logo) >= 1 && (strpos($settings->company_logo, 'http') !== false)) {
return "data:image/png;base64, ". base64_encode(@file_get_contents($settings->company_logo, false, stream_context_create($context_options))); return "data:image/png;base64,". base64_encode(@file_get_contents($settings->company_logo, false, stream_context_create($context_options)));
} elseif (strlen($settings->company_logo) >= 1) { } elseif (strlen($settings->company_logo) >= 1) {
return "data:image/png;base64, ". base64_encode(@file_get_contents(url('') . $settings->company_logo, false, stream_context_create($context_options))); return "data:image/png;base64,". base64_encode(@file_get_contents(url('') . $settings->company_logo, false, stream_context_create($context_options)));
} else { } else {
return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="; return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=";
} }

View File

@ -22,6 +22,7 @@ use Illuminate\Support\Carbon;
* App\Models\PurchaseOrder * App\Models\PurchaseOrder
* *
* @property int $id * @property int $id
* @property object|null $e_invoice
* @property int|null $client_id * @property int|null $client_id
* @property int $user_id * @property int $user_id
* @property int|null $assigned_user_id * @property int|null $assigned_user_id
@ -187,7 +188,7 @@ class PurchaseOrder extends BaseModel
'created_at' => 'timestamp', 'created_at' => 'timestamp',
'deleted_at' => 'timestamp', 'deleted_at' => 'timestamp',
'is_amount_discount' => 'bool', 'is_amount_discount' => 'bool',
'e_invoice' => 'object',
]; ];
public const STATUS_DRAFT = 1; public const STATUS_DRAFT = 1;

View File

@ -27,6 +27,7 @@ use Laracasts\Presenter\PresentableTrait;
* App\Models\Quote * App\Models\Quote
* *
* @property int $id * @property int $id
* @property object|null $e_invoice
* @property int $client_id * @property int $client_id
* @property int $user_id * @property int $user_id
* @property int|null $assigned_user_id * @property int|null $assigned_user_id
@ -174,6 +175,7 @@ class Quote extends BaseModel
'deleted_at' => 'timestamp', 'deleted_at' => 'timestamp',
'is_deleted' => 'boolean', 'is_deleted' => 'boolean',
'is_amount_discount' => 'bool', 'is_amount_discount' => 'bool',
'e_invoice' => 'object',
]; ];
public const STATUS_DRAFT = 1; public const STATUS_DRAFT = 1;

View File

@ -152,6 +152,8 @@ class SystemLog extends Model
public const TYPE_PAYPAL_PPCP = 323; public const TYPE_PAYPAL_PPCP = 323;
public const TYPE_BTC_PAY = 324;
public const TYPE_QUOTA_EXCEEDED = 400; public const TYPE_QUOTA_EXCEEDED = 400;
public const TYPE_UPSTREAM_FAILURE = 401; public const TYPE_UPSTREAM_FAILURE = 401;

View File

@ -67,7 +67,7 @@ class AuthorizePaymentDriver extends BaseDriver
public function getClientRequiredFields(): array public function getClientRequiredFields(): array
{ {
$data = [ $data = [
['name' => 'client_name', 'label' => ctrans('texts.name'), 'type' => 'text', 'validation' => 'required|min:2'], // ['name' => 'client_name', 'label' => ctrans('texts.name'), 'type' => 'text', 'validation' => 'required|min:2'],
['name' => 'client_phone', 'label' => ctrans('texts.phone'), 'type' => 'text', 'validation' => 'required'], ['name' => 'client_phone', 'label' => ctrans('texts.phone'), 'type' => 'text', 'validation' => 'required'],
['name' => 'contact_email', 'label' => ctrans('texts.email'), 'type' => 'text', 'validation' => 'required|email:rfc'], ['name' => 'contact_email', 'label' => ctrans('texts.email'), 'type' => 'text', 'validation' => 'required|email:rfc'],
['name' => 'client_address_line_1', 'label' => ctrans('texts.address1'), 'type' => 'text', 'validation' => 'required'], ['name' => 'client_address_line_1', 'label' => ctrans('texts.address1'), 'type' => 'text', 'validation' => 'required'],

View File

@ -0,0 +1,426 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\PaymentDrivers\PayPal;
use Str;
use Carbon\Carbon;
use App\Models\Invoice;
use App\Models\SystemLog;
use App\Models\GatewayType;
use App\Models\PaymentType;
use Illuminate\Http\Request;
use App\Jobs\Util\SystemLogger;
use App\Utils\Traits\MakesHash;
use App\Exceptions\PaymentFailed;
use App\Models\ClientGatewayToken;
use App\PaymentDrivers\BaseDriver;
use Illuminate\Support\Facades\Http;
use App\PaymentDrivers\PayPal\PayPalWebhook;
class PayPalBasePaymentDriver extends BaseDriver
{
use MakesHash;
public $token_billing = true;
public $can_authorise_credit_card = false;
public float $fee = 0;
public const SYSTEM_LOG_TYPE = SystemLog::TYPE_PAYPAL;
public string $api_endpoint_url = '';
public string $paypal_payment_method = '';
public ?int $gateway_type_id = null;
public mixed $access_token = null;
public ?Carbon $token_expiry = null;
public array $funding_options = [
3 => 'paypal',
1 => 'card',
25 => 'venmo',
29 => 'paypal_advanced_cards',
// 9 => 'sepa',
// 12 => 'bancontact',
// 17 => 'eps',
// 15 => 'giropay',
// 13 => 'ideal',
// 26 => 'mercadopago',
// 27 => 'mybank',
28 => 'paylater',
// 16 => 'p24',
// 7 => 'sofort'
];
public function gatewayTypes()
{
$funding_options =
collect($this->company_gateway->fees_and_limits)
->filter(function ($fee) {
return $fee->is_enabled;
})->map(function ($fee, $key) {
return (int)$key;
})->toArray();
/** Parse funding options and remove card option if advanced cards is enabled. */
if(in_array(1, $funding_options) && in_array(29, $funding_options)){
if (($key = array_search(1, $funding_options)) !== false)
unset($funding_options[$key]);
}
return $funding_options;
}
public function getPaymentMethod($gateway_type_id): int
{
$method = PaymentType::PAYPAL;
match($gateway_type_id) {
"1" => $method = PaymentType::CREDIT_CARD_OTHER,
"3" => $method = PaymentType::PAYPAL,
"25" => $method = PaymentType::VENMO,
"28" => $method = PaymentType::PAY_LATER,
"29" => $method = PaymentType::CREDIT_CARD_OTHER,
};
return $method;
}
public function init()
{
$this->api_endpoint_url = $this->company_gateway->getConfigField('testMode') ? 'https://api-m.sandbox.paypal.com' : 'https://api-m.paypal.com';
$secret = $this->company_gateway->getConfigField('secret');
$client_id = $this->company_gateway->getConfigField('clientId');
if($this->access_token && $this->token_expiry && $this->token_expiry->isFuture()) {
return $this;
}
$response = Http::withBasicAuth($client_id, $secret)
->withHeaders(['Content-Type' => 'application/x-www-form-urlencoded'])
->withQueryParameters(['grant_type' => 'client_credentials'])
->post("{$this->api_endpoint_url}/v1/oauth2/token");
if($response->successful()) {
$this->access_token = $response->json()['access_token'];
$this->token_expiry = now()->addSeconds($response->json()['expires_in'] - 60);
} else {
throw new PaymentFailed('Unable to gain access token from Paypal. Check your configuration', 401);
}
return $this;
}
/**
* getFundingOptions
*
* Hosted fields requires this.
*
* @return string
*/
public function getFundingOptions(): string
{
$enums = [
1 => 'card',
3 => 'paypal',
25 => 'venmo',
28 => 'paylater',
// 9 => 'sepa',
// 12 => 'bancontact',
// 17 => 'eps',
// 15 => 'giropay',
// 13 => 'ideal',
// 26 => 'mercadopago',
// 27 => 'mybank',
// 28 => 'paylater',
// 16 => 'p24',
// 7 => 'sofort'
];
$funding_options = '';
foreach($this->company_gateway->fees_and_limits as $key => $value) {
if($value->is_enabled) {
$funding_options .= $enums[$key].',';
}
}
return rtrim($funding_options, ',');
}
public function getShippingAddress(): ?array
{
return $this->company_gateway->require_shipping_address ?
[
"address" =>
[
"address_line_1" => strlen($this->client->shipping_address1) > 1 ? $this->client->shipping_address1 : $this->client->address1,
"address_line_2" => $this->client->shipping_address2,
"admin_area_2" => strlen($this->client->shipping_city) > 1 ? $this->client->shipping_city : $this->client->city,
"admin_area_1" => strlen($this->client->shipping_state) > 1 ? $this->client->shipping_state : $this->client->state,
"postal_code" => strlen($this->client->shipping_postal_code) > 1 ? $this->client->shipping_postal_code : $this->client->postal_code,
"country_code" => $this->client->present()->shipping_country_code(),
],
]
: [
"name" => [
"full_name" => $this->client->present()->name()
]
];
}
public function getBillingAddress(): array
{
return
[
"address_line_1" => $this->client->address1,
"address_line_2" => $this->client->address2,
"admin_area_2" => $this->client->city,
"admin_area_1" => $this->client->state,
"postal_code" => $this->client->postal_code,
"country_code" => $this->client->country->iso_3166_2,
];
}
public function getPaymentSource(): array
{
//@todo - roll back here for advanced payments vs hosted card fields.
if($this->gateway_type_id == GatewayType::PAYPAL_ADVANCED_CARDS) {
return [
"card" => [
"attributes" => [
"verification" => [
"method" => "SCA_WHEN_REQUIRED", //SCA_ALWAYS
// "method" => "SCA_ALWAYS", //SCA_ALWAYS
],
"vault" => [
"store_in_vault" => "ON_SUCCESS", //must listen to this webhook - VAULT.PAYMENT-TOKEN.CREATED webhook.
],
],
"experience_context" => [
"shipping_preference" => "SET_PROVIDED_ADDRESS"
],
"stored_credential" => [
// "payment_initiator" => "MERCHANT", //"CUSTOMER" who initiated the transaction?
"payment_initiator" => "CUSTOMER", //"" who initiated the transaction?
"payment_type" => "UNSCHEDULED", //UNSCHEDULED
"usage"=> "DERIVED",
],
],
];
}
$order = [
"paypal" => [
"name" => [
"given_name" => $this->client->present()->first_name(),
"surname" => $this->client->present()->last_name(),
],
"email_address" => $this->client->present()->email(),
"experience_context" => [
"user_action" => "PAY_NOW"
],
],
];
/** If we have a complete address, add it to the order, otherwise leave it blank! */
if(
strlen($this->client->shipping_address1 ?? '') > 2 &&
strlen($this->client->shipping_city ?? '') > 2 &&
strlen($this->client->shipping_state ?? '') >= 2 &&
strlen($this->client->shipping_postal_code ?? '') > 2 &&
strlen($this->client->shipping_country->iso_3166_2 ?? '') >= 2
) {
$order['paypal']['address'] = [
"address_line_1" => $this->client->shipping_address1,
"address_line_2" => $this->client->shipping_address2,
"admin_area_2" => $this->client->shipping_city,
"admin_area_1" => $this->client->shipping_state,
"postal_code" => $this->client->shipping_postal_code,
"country_code" => $this->client->present()->shipping_country_code(),
];
}
elseif(
strlen($this->client->address1 ?? '') > 2 &&
strlen($this->client->city ?? '') > 2 &&
strlen($this->client->state ?? '') >= 2 &&
strlen($this->client->postal_code ?? '') > 2 &&
strlen($this->client->country->iso_3166_2 ?? '') >= 2
)
{
$order['paypal']['address'] = [
"address_line_1" => $this->client->address1,
"address_line_2" => $this->client->address2,
"admin_area_2" => $this->client->city,
"admin_area_1" => $this->client->state,
"postal_code" => $this->client->postal_code,
"country_code" => $this->client->country->iso_3166_2,
];
}
return $order;
}
/**
* Payment method setter
*
* @param mixed $payment_method_id
* @return self
*/
public function setPaymentMethod($payment_method_id): self
{
if(!$payment_method_id) {
return $this;
}
$this->gateway_type_id = $payment_method_id;
$this->paypal_payment_method = $this->funding_options[$payment_method_id];
return $this;
}
public function authorizeView($payment_method)
{
// PayPal doesn't support direct authorization.
return $this;
}
public function authorizeResponse($request)
{
// PayPal doesn't support direct authorization.
return $this;
}
/**
* Generates the gateway request
*
* @param string $uri
* @param string $verb
* @param array $data
* @param ?array $headers
* @return \Illuminate\Http\Client\Response
*/
public function gatewayRequest(string $uri, string $verb, array $data, ?array $headers = [])
{
$this->init();
$r = Http::withToken($this->access_token)
->withHeaders($this->getHeaders($headers))
->{$verb}("{$this->api_endpoint_url}{$uri}", $data);
if($r->successful()) {
return $r;
}
SystemLogger::dispatch(
['response' => $r->body()],
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_FAILURE,
SystemLog::TYPE_PAYPAL,
$this->client,
$this->client->company ?? $this->company_gateway->company,
);
throw new PaymentFailed("Gateway failure - {$r->body()}", 401);
}
/**
* Generates the request headers
*
* @param array $headers
* @return array
*/
public function getHeaders(array $headers = []): array
{
return array_merge([
'Accept' => 'application/json',
'Content-type' => 'application/json',
'Accept-Language' => 'en_US',
'PayPal-Partner-Attribution-Id' => 'invoiceninja_SP_PPCP',
'PayPal-Request-Id' => Str::uuid()->toString(),
], $headers);
}
/**
* Generates a client token for the payment form.
*
* @return string
*/
public function getClientToken(): string
{
$r = $this->gatewayRequest('/v1/identity/generate-token', 'post', ['body' => '']);
if($r->successful()) {
return $r->json()['client_token'];
}
throw new PaymentFailed('Unable to gain client token from Paypal. Check your configuration', 401);
}
public function auth(): bool
{
try {
$this->init()->getClientToken();
return true;
}
catch(\Exception $e) {
}
return false;
}
public function importCustomers()
{
return true;
}
public function processWebhookRequest(Request $request)
{
$this->init();
PayPalWebhook::dispatch($request->all(), $request->headers->all(), $this->access_token);
}
}

View File

@ -21,188 +21,34 @@ use Illuminate\Http\Request;
use App\Jobs\Util\SystemLogger; use App\Jobs\Util\SystemLogger;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use App\Exceptions\PaymentFailed; use App\Exceptions\PaymentFailed;
use App\Models\ClientGatewayToken;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
use App\PaymentDrivers\PayPal\PayPalWebhook; use App\PaymentDrivers\PayPal\PayPalWebhook;
use App\PaymentDrivers\PayPal\PayPalBasePaymentDriver;
class PayPalPPCPPaymentDriver extends BaseDriver class PayPalPPCPPaymentDriver extends PayPalBasePaymentDriver
{ {
use MakesHash; use MakesHash;
public $token_billing = false; ///v1/customer/partners/merchant-accounts/{merchant_id}/capabilities - test if advanced cards is available.
// {
public $can_authorise_credit_card = false; // "capabilities": [
// {
private $omnipay_gateway; // "name": "ADVANCED_CARD_PAYMENTS",
// "status": "ENABLED"
private float $fee = 0; // },
// {
// "name": "VAULTING",
// "status": "ENABLED"
// }
// ]
// }
public const SYSTEM_LOG_TYPE = SystemLog::TYPE_PAYPAL_PPCP; public const SYSTEM_LOG_TYPE = SystemLog::TYPE_PAYPAL_PPCP;
private string $api_endpoint_url = '';
private string $paypal_payment_method = '';
private ?int $gateway_type_id = null;
protected mixed $access_token = null;
protected ?Carbon $token_expiry = null;
private array $funding_options = [
3 => 'paypal',
1 => 'card',
25 => 'venmo',
// 9 => 'sepa',
// 12 => 'bancontact',
// 17 => 'eps',
// 15 => 'giropay',
// 13 => 'ideal',
// 26 => 'mercadopago',
// 27 => 'mybank',
28 => 'paylater',
// 16 => 'p24',
// 7 => 'sofort'
];
/** /**
* Return an array of * Checks whether payments are enabled on the merchant account
* enabled gateway payment methods *
*
* @return array
*/
public function gatewayTypes(): array
{
return collect($this->company_gateway->fees_and_limits)
->filter(function ($fee) {
return $fee->is_enabled;
})->map(function ($fee, $key) {
return (int)$key;
})->toArray();
}
private function getPaymentMethod($gateway_type_id): int
{
$method = PaymentType::PAYPAL;
match($gateway_type_id) {
"1" => $method = PaymentType::CREDIT_CARD_OTHER,
"3" => $method = PaymentType::PAYPAL,
"25" => $method = PaymentType::VENMO,
"28" => $method = PaymentType::PAY_LATER,
};
return $method;
}
private function getFundingOptions(): string
{
$enums = [
1 => 'card',
3 => 'paypal',
25 => 'venmo',
28 => 'paylater',
// 9 => 'sepa',
// 12 => 'bancontact',
// 17 => 'eps',
// 15 => 'giropay',
// 13 => 'ideal',
// 26 => 'mercadopago',
// 27 => 'mybank',
// 28 => 'paylater',
// 16 => 'p24',
// 7 => 'sofort'
];
$funding_options = '';
foreach($this->company_gateway->fees_and_limits as $key => $value) {
if($value->is_enabled) {
$funding_options .= $enums[$key].',';
}
}
return rtrim($funding_options, ',');
}
/**
* Initialize the Paypal gateway.
*
* Attempt to generate and return the access token.
*
* @return self
*/
public function init(): self
{
$this->api_endpoint_url = 'https://api-m.paypal.com';
// $this->api_endpoint_url = 'https://api-m.sandbox.paypal.com';
$secret = config('ninja.paypal.secret');
$client_id = config('ninja.paypal.client_id');
if($this->access_token && $this->token_expiry && $this->token_expiry->isFuture()) {
return $this;
}
$response = Http::withBasicAuth($client_id, $secret)
->withHeaders(['Content-Type' => 'application/x-www-form-urlencoded'])
->withQueryParameters(['grant_type' => 'client_credentials'])
->post("{$this->api_endpoint_url}/v1/oauth2/token");
if($response->successful()) {
$this->access_token = $response->json()['access_token'];
$this->token_expiry = now()->addSeconds($response->json()['expires_in'] - 60);
} else {
throw new PaymentFailed('Unable to gain access token from Paypal. Check your configuration', 401);
}
return $this;
}
/**
* Payment method setter
*
* @param mixed $payment_method_id
* @return self
*/
public function setPaymentMethod($payment_method_id): self
{
if(!$payment_method_id) {
return $this;
}
$this->gateway_type_id = $payment_method_id;
$this->paypal_payment_method = $this->funding_options[$payment_method_id];
return $this;
}
public function authorizeView($payment_method)
{
// PayPal doesn't support direct authorization.
return $this;
}
public function authorizeResponse($request)
{
// PayPal doesn't support direct authorization.
return $this;
}
/**
* Checks whether payments are enabled on the account
*
* @return self * @return self
*/ */
private function checkPaymentsReceivable(): self private function checkPaymentsReceivable(): self
@ -252,7 +98,10 @@ class PayPalPPCPPaymentDriver extends BaseDriver
$data['merchantId'] = $this->company_gateway->getConfigField('merchantId'); $data['merchantId'] = $this->company_gateway->getConfigField('merchantId');
$data['currency'] = $this->client->currency()->code; $data['currency'] = $this->client->currency()->code;
return render('gateways.paypal.ppcp.pay', $data); if($this->gateway_type_id == 29)
return render('gateways.paypal.ppcp.card', $data);
else
return render('gateways.paypal.ppcp.pay', $data);
} }
@ -268,6 +117,10 @@ class PayPalPPCPPaymentDriver extends BaseDriver
$request['gateway_response'] = str_replace("Error: ", "", $request['gateway_response']); $request['gateway_response'] = str_replace("Error: ", "", $request['gateway_response']);
$response = json_decode($request['gateway_response'], true); $response = json_decode($request['gateway_response'], true);
if($request->has('token') && strlen($request->input('token')) > 2) {
return $this->processTokenPayment($request, $response);
}
//capture //capture
$orderID = $response['orderID']; $orderID = $response['orderID'];
@ -335,7 +188,7 @@ class PayPalPPCPPaymentDriver extends BaseDriver
['response' => $response, 'data' => $data], ['response' => $response, 'data' => $data],
SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::EVENT_GATEWAY_SUCCESS,
SystemLog::TYPE_PAYPAL, SystemLog::TYPE_PAYPAL_PPCP,
$this->client, $this->client,
$this->client->company, $this->client->company,
); );
@ -352,7 +205,7 @@ class PayPalPPCPPaymentDriver extends BaseDriver
['response' => $response], ['response' => $response],
SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::EVENT_GATEWAY_FAILURE,
SystemLog::TYPE_PAYPAL, SystemLog::TYPE_PAYPAL_PPCP,
$this->client, $this->client,
$this->client->company, $this->client->company,
); );
@ -372,74 +225,13 @@ class PayPalPPCPPaymentDriver extends BaseDriver
return $r->json(); return $r->json();
} }
/**
* Generates a client token for the payment form.
*
* @return string
*/
private function getClientToken(): string
{
$r = $this->gatewayRequest('/v1/identity/generate-token', 'post', ['body' => '']);
if($r->successful()) {
return $r->json()['client_token'];
}
throw new PaymentFailed('Unable to gain client token from Paypal. Check your configuration', 401);
}
/**
* Builds the payment request.
*
* @return array
*/
private function paymentSource(): array
{
/** we only need to support paypal as payment source until as we are only using hosted payment buttons */
return $this->injectPayPalPaymentSource();
}
private function injectPayPalPaymentSource(): array
{
$order = [
"paypal" => [
"name" => [
"given_name" => $this->client->present()->first_name(),
"surname" => $this->client->present()->last_name(),
],
"email_address" => $this->client->present()->email(),
"experience_context" => [
"user_action" => "PAY_NOW"
],
],
];
if(
strlen($this->client->address1 ?? '') > 2 &&
strlen($this->client->city ?? '') > 2 &&
strlen($this->client->state ?? '') >= 2 &&
strlen($this->client->postal_code ?? '') > 2 &&
strlen($this->client->country->iso_3166_2 ?? '') >= 2
)
{
$order["paypal"]["address"] = $this->getBillingAddress();
}
return $order;
}
/** /**
* Creates the PayPal Order object * Creates the PayPal Order object
* *
* @param array $data * @param array $data
* @return string * @return string
*/ */
private function createOrder(array $data): string public function createOrder(array $data): string
{ {
$_invoice = collect($this->payment_hash->data->invoices)->first(); $_invoice = collect($this->payment_hash->data->invoices)->first();
@ -453,7 +245,7 @@ class PayPalPPCPPaymentDriver extends BaseDriver
$order = [ $order = [
"intent" => "CAPTURE", "intent" => "CAPTURE",
"payment_source" => $this->paymentSource(), "payment_source" => $this->getPaymentSource(),
"purchase_units" => [ "purchase_units" => [
[ [
"custom_id" => $this->payment_hash->hash, "custom_id" => $this->payment_hash->hash,
@ -465,7 +257,6 @@ class PayPalPPCPPaymentDriver extends BaseDriver
"payment_instruction" => [ "payment_instruction" => [
"disbursement_mode" => "INSTANT", "disbursement_mode" => "INSTANT",
], ],
$this->getShippingAddress(),
"amount" => [ "amount" => [
"value" => (string)$data['amount_with_fee'], "value" => (string)$data['amount_with_fee'],
"currency_code" => $this->client->currency()->code, "currency_code" => $this->client->currency()->code,
@ -496,125 +287,76 @@ class PayPalPPCPPaymentDriver extends BaseDriver
$order['purchase_units'][0]["shipping"] = $shipping; $order['purchase_units'][0]["shipping"] = $shipping;
} }
if(isset($data['payment_source'])) {
$order['payment_source'] = $data['payment_source'];
}
$r = $this->gatewayRequest('/v2/checkout/orders', 'post', $order); $r = $this->gatewayRequest('/v2/checkout/orders', 'post', $order);
return $r->json()['id']; return $r->json()['id'];
} }
private function getBillingAddress(): array
{
return
[
"address_line_1" => $this->client->address1,
"address_line_2" => $this->client->address2,
"admin_area_2" => $this->client->city,
"admin_area_1" => $this->client->state,
"postal_code" => $this->client->postal_code,
"country_code" => $this->client->country->iso_3166_2,
];
}
private function getShippingAddress(): ?array
{
return $this->company_gateway->require_shipping_address ?
[
"address" =>
[
"address_line_1" => strlen($this->client->shipping_address1 ?? '') > 1 ? $this->client->shipping_address1 : $this->client->address1,
"address_line_2" => $this->client->shipping_address2,
"admin_area_2" => strlen($this->client->shipping_city ?? '') > 1 ? $this->client->shipping_city : $this->client->city,
"admin_area_1" => strlen($this->client->shipping_state ?? '') > 1 ? $this->client->shipping_state : $this->client->state,
"postal_code" => strlen($this->client->shipping_postal_code ?? '') > 1 ? $this->client->shipping_postal_code : $this->client->postal_code,
"country_code" => $this->client->present()->shipping_country_code(),
],
]
: null;
}
/** /**
* Generates the gateway request * processTokenPayment
* *
* @param string $uri * With PayPal and token payments, the order needs to be
* @param string $verb * deleted and then created with the payment source that
* @param array $data * has been selected by the client.
* @param ?array $headers *
* @return \Illuminate\Http\Client\Response * This method handle the deletion of the current paypal order,
* and the automatic payment of the order with the selected payment source.
*
* @param mixed $request
* @param array $response
* @return void
*/ */
public function gatewayRequest(string $uri, string $verb, array $data, ?array $headers = []) public function processTokenPayment($request, array $response) {
{
$this->init();
$r = Http::withToken($this->access_token) $cgt = ClientGatewayToken::where('client_id', $this->client->id)
->withHeaders($this->getHeaders($headers)) ->where('token', $request['token'])
->{$verb}("{$this->api_endpoint_url}{$uri}", $data); ->firstOrFail();
if($r->successful()) { $orderId = $response['orderID'];
return $r; $r = $this->gatewayRequest("/v1/checkout/orders/{$orderId}/", 'delete', ['body' => '']);
}
$data['amount_with_fee'] = $this->payment_hash->data->amount_with_fee;
$data["payment_source"] = [
"card" => [
"vault_id" => $cgt->token,
"stored_credential" => [
"payment_initiator" => "MERCHANT",
"payment_type" => "UNSCHEDULED",
"usage" => "SUBSEQUENT",
],
],
];
$orderId = $this->createOrder($data);
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderId}", 'get', ['body' => '']);
$response = $r->json();
$data = [
'payment_type' => $this->getPaymentMethod($request->gateway_type_id),
'amount' => $response['purchase_units'][0]['payments']['captures'][0]['amount']['value'],
'transaction_reference' => $response['purchase_units'][0]['payments']['captures'][0]['id'],
'gateway_type_id' => $this->gateway_type_id,
];
$payment = $this->createPayment($data, \App\Models\Payment::STATUS_COMPLETED);
SystemLogger::dispatch( SystemLogger::dispatch(
['response' => $r->body()], ['response' => $response, 'data' => $data],
SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::EVENT_GATEWAY_SUCCESS,
SystemLog::TYPE_PAYPAL, SystemLog::TYPE_PAYPAL_PPCP,
$this->client, $this->client,
$this->client->company, $this->client->company,
); );
throw new PaymentFailed("Gateway failure - {$r->body()}", 401); return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]);
} }
}
/**
* Generates the request headers
*
* @param array $headers
* @return array
*/
private function getHeaders(array $headers = []): array
{
return array_merge([
'Accept' => 'application/json',
'Content-type' => 'application/json',
'Accept-Language' => 'en_US',
'PayPal-Partner-Attribution-Id' => 'invoiceninja_SP_PPCP',
'PayPal-Request-Id' => Str::uuid()->toString(),
], $headers);
}
public function processWebhookRequest(Request $request)
{
// nlog(json_encode($request->all()));
$this->init();
PayPalWebhook::dispatch($request->all(), $request->headers->all(), $this->access_token);
}
public function auth(): bool
{
try {
$this->init()->getClientToken();
return true;
}
catch(\Exception $e) {
}
return false;
}
public function importCustomers()
{
// $response = $this->gatewayRequest('/v1/reporting/transactions', 'get', ['fields' => 'all','page_size' => 500,'start_date' => '2024-02-01T00:00:00-0000', 'end_date' => '2024-03-01T00:00:00-0000']);
// nlog($response->json());
return true;
}
}

View File

@ -12,147 +12,22 @@
namespace App\PaymentDrivers; namespace App\PaymentDrivers;
use Carbon\Carbon;
use Omnipay\Omnipay;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\SystemLog; use App\Models\SystemLog;
use App\Models\GatewayType; use App\Models\GatewayType;
use App\Models\PaymentType;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use App\Jobs\Util\SystemLogger; use App\Jobs\Util\SystemLogger;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use App\Exceptions\PaymentFailed; use App\Exceptions\PaymentFailed;
use App\Models\ClientGatewayToken; use App\Models\ClientGatewayToken;
use Illuminate\Support\Facades\Http; use App\PaymentDrivers\PayPal\PayPalBasePaymentDriver;
class PayPalRestPaymentDriver extends BaseDriver class PayPalRestPaymentDriver extends PayPalBasePaymentDriver
{ {
use MakesHash; use MakesHash;
public $token_billing = false;
public $can_authorise_credit_card = false;
private $omnipay_gateway;
private float $fee = 0;
public const SYSTEM_LOG_TYPE = SystemLog::TYPE_PAYPAL; public const SYSTEM_LOG_TYPE = SystemLog::TYPE_PAYPAL;
private string $api_endpoint_url = '';
private string $paypal_payment_method = '';
private ?int $gateway_type_id = null;
protected mixed $access_token = null;
protected ?Carbon $token_expiry = null;
private array $funding_options = [
3 => 'paypal',
1 => 'card',
25 => 'venmo',
29 => 'paypal_advanced_cards',
// 9 => 'sepa',
// 12 => 'bancontact',
// 17 => 'eps',
// 15 => 'giropay',
// 13 => 'ideal',
// 26 => 'mercadopago',
// 27 => 'mybank',
28 => 'paylater',
// 16 => 'p24',
// 7 => 'sofort'
];
public function gatewayTypes()
{
$funding_options = [];
foreach ($this->company_gateway->fees_and_limits as $key => $value) {
if ($value->is_enabled) {
$funding_options[] = $key;
}
}
return $funding_options;
}
public function init()
{
$this->api_endpoint_url = $this->company_gateway->getConfigField('testMode') ? 'https://api-m.sandbox.paypal.com' : 'https://api-m.paypal.com';
$secret = $this->company_gateway->getConfigField('secret');
$client_id = $this->company_gateway->getConfigField('clientId');
if($this->access_token && $this->token_expiry && $this->token_expiry->isFuture()) {
return $this;
}
$response = Http::withBasicAuth($client_id, $secret)
->withHeaders(['Content-Type' => 'application/x-www-form-urlencoded'])
->withQueryParameters(['grant_type' => 'client_credentials'])
->post("{$this->api_endpoint_url}/v1/oauth2/token");
if($response->successful()) {
$this->access_token = $response->json()['access_token'];
$this->token_expiry = now()->addSeconds($response->json()['expires_in'] - 60);
} else {
throw new PaymentFailed('Unable to gain access token from Paypal. Check your configuration', 401);
}
return $this;
}
private function getPaymentMethod($gateway_type_id): int
{
$method = PaymentType::PAYPAL;
match($gateway_type_id) {
"1" => $method = PaymentType::CREDIT_CARD_OTHER,
"3" => $method = PaymentType::PAYPAL,
"25" => $method = PaymentType::VENMO,
"28" => $method = PaymentType::PAY_LATER,
"29" => $method = PaymentType::CREDIT_CARD_OTHER,
};
return $method;
}
public function setPaymentMethod($payment_method_id): self
{
if(!$payment_method_id) {
return $this;
}
$this->gateway_type_id = $payment_method_id;
$this->paypal_payment_method = $this->funding_options[$payment_method_id];
return $this;
}
public function authorizeView($payment_method)
{
// PayPal doesn't support direct authorization.
return $this;
}
public function authorizeResponse($request)
{
// PayPal doesn't support direct authorization.
return $this;
}
public function processPaymentView($data) public function processPaymentView($data)
{ {
$this->init(); $this->init();
@ -169,110 +44,20 @@ class PayPalRestPaymentDriver extends BaseDriver
$data['gateway_type_id'] = $this->gateway_type_id; $data['gateway_type_id'] = $this->gateway_type_id;
$data['currency'] = $this->client->currency()->code; $data['currency'] = $this->client->currency()->code;
if($this->gateway_type_id == 29)
// return render('gateways.paypal.ppcp.card', $data); return render('gateways.paypal.ppcp.card', $data);
else
return render('gateways.paypal.pay', $data); return render('gateways.paypal.pay', $data);
} }
private function getFundingOptions(): string
{ /**
* processPaymentResponse
$enums = [ *
3 => 'paypal', * @param mixed $request
1 => 'card', * @return void
25 => 'venmo', */
// 9 => 'sepa',
// 12 => 'bancontact',
// 17 => 'eps',
// 15 => 'giropay',
// 13 => 'ideal',
// 26 => 'mercadopago',
// 27 => 'mybank',
// 28 => 'paylater',
// 16 => 'p24',
// 7 => 'sofort'
];
$funding_options = '';
foreach($this->company_gateway->fees_and_limits as $key => $value) {
if($value->is_enabled) {
$funding_options .= $enums[$key].',';
}
}
return rtrim($funding_options, ',');
}
public function processTokenPayment($request, array $response) {
$cgt = ClientGatewayToken::where('client_id', $this->client->id)
->where('token', $request['token'])
->firstOrFail();
nlog("process token");
nlog($request->all());
nlog($response);
$orderId = $response['orderID'];
$r = $this->gatewayRequest("/v1/checkout/orders/{$orderId}/", 'delete', ['body' => '']);
nlog($r);
$data['amount_with_fee'] = $this->payment_hash->data->amount_with_fee;
$data["payment_source"] = [
"card" => [
"vault_id" => $cgt->token,
"stored_credential" => [
"payment_initiator" => "MERCHANT",
"payment_type" => "UNSCHEDULED",
"usage" => "SUBSEQUENT",
// "previous_transaction_reference" => $cgt->gateway_customer_reference,
],
],
];
$orderId = $this->createOrder($data);
nlog("post order creation");
nlog($orderId);
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderId}", 'get', ['body' => '']);
nlog($r);
$response = $r->json();
nlog($response);
$data = [
'payment_type' => $this->getPaymentMethod($request->gateway_type_id),
'amount' => $response['purchase_units'][0]['payments']['captures'][0]['amount']['value'],
'transaction_reference' => $response['purchase_units'][0]['payments']['captures'][0]['id'],
'gateway_type_id' => $this->gateway_type_id,
];
$payment = $this->createPayment($data, \App\Models\Payment::STATUS_COMPLETED);
SystemLogger::dispatch(
['response' => $response, 'data' => $data],
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_SUCCESS,
SystemLog::TYPE_PAYPAL,
$this->client,
$this->client->company,
);
return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]);
}
public function processPaymentResponse($request) public function processPaymentResponse($request)
{ {
@ -280,12 +65,10 @@ return render('gateways.paypal.pay', $data);
$request['gateway_response'] = str_replace("Error: ", "", $request['gateway_response']); $request['gateway_response'] = str_replace("Error: ", "", $request['gateway_response']);
$response = json_decode($request['gateway_response'], true); $response = json_decode($request['gateway_response'], true);
nlog($request->all());
if($request->has('token') && strlen($request->input('token')) > 2) if($request->has('token') && strlen($request->input('token')) > 2)
return $this->processTokenPayment($request, $response); return $this->processTokenPayment($request, $response);
// nlog($response);
//capture //capture
$orderID = $response['orderID']; $orderID = $response['orderID'];
@ -339,6 +122,9 @@ return render('gateways.paypal.pay', $data);
$response = $r; $response = $r;
nlog("Process response =>");
nlog($response->json());
if(isset($response['status']) && $response['status'] == 'COMPLETED' && isset($response['purchase_units'])) { if(isset($response['status']) && $response['status'] == 'COMPLETED' && isset($response['purchase_units'])) {
return $this->createNinjaPayment($request, $response); return $this->createNinjaPayment($request, $response);
@ -367,8 +153,6 @@ return render('gateways.paypal.pay', $data);
private function createNinjaPayment($request, $response) { private function createNinjaPayment($request, $response) {
nlog($response->json());
$data = [ $data = [
'payment_type' => $this->getPaymentMethod($request->gateway_type_id), 'payment_type' => $this->getPaymentMethod($request->gateway_type_id),
'amount' => $response['purchase_units'][0]['payments']['captures'][0]['amount']['value'], 'amount' => $response['purchase_units'][0]['payments']['captures'][0]['amount']['value'],
@ -401,7 +185,6 @@ return render('gateways.paypal.pay', $data);
$data['token'] = $token; $data['token'] = $token;
$data['payment_method_id'] = GatewayType::PAYPAL_ADVANCED_CARDS; $data['payment_method_id'] = GatewayType::PAYPAL_ADVANCED_CARDS;
$data['payment_meta'] = $payment_meta; $data['payment_meta'] = $payment_meta;
// $data['payment_method_id'] = GatewayType::CREDIT_CARD;
$additional['gateway_customer_reference'] = $gateway_customer_reference; $additional['gateway_customer_reference'] = $gateway_customer_reference;
@ -423,116 +206,7 @@ return render('gateways.paypal.pay', $data);
} }
private function getClientToken(): string public function createOrder(array $data): string
{
$r = $this->gatewayRequest('/v1/identity/generate-token', 'post', ['body' => '']);
if($r->successful()) {
return $r->json()['client_token'];
}
throw new PaymentFailed('Unable to gain client token from Paypal. Check your configuration', 401);
}
private function getPaymentSource(): array
{
//@todo - roll back here for advanced payments vs hosted card fields.
if($this->gateway_type_id == GatewayType::PAYPAL_ADVANCED_CARDS) {
return [
"card" => [
"attributes" => [
"verification" => [
"method" => "SCA_WHEN_REQUIRED", //SCA_ALWAYS
// "method" => "SCA_ALWAYS", //SCA_ALWAYS
],
"vault" => [
"store_in_vault" => "ON_SUCCESS", //must listen to this webhook - VAULT.PAYMENT-TOKEN.CREATED webhook.
],
],
"experience_context" => [
"shipping_preference" => "SET_PROVIDED_ADDRESS"
],
// "name" => $this->client->present()->primary_contact_name(),
// "email_address" => $this->client->present()->email(),
// "address" => [
// "address_line_1" => $this->client->address1,
// "address_line_2" => $this->client->address2,
// "admin_area_2" => $this->client->city,
// "admin_area_1" => $this->client->state,
// "postal_code" => $this->client->postal_code,
// "country_code" => $this->client->country->iso_3166_2,
// ],
// "experience_context" => [
// "user_action" => "PAY_NOW"
// ],
"stored_credential" => [
// "payment_initiator" => "MERCHANT", //"CUSTOMER" who initiated the transaction?
"payment_initiator" => "CUSTOMER", //"" who initiated the transaction?
"payment_type" => "UNSCHEDULED", //UNSCHEDULED
"usage"=> "DERIVED",
],
],
];
}
$order = [
"paypal" => [
"name" => [
"given_name" => $this->client->present()->first_name(),
"surname" => $this->client->present()->last_name(),
],
"email_address" => $this->client->present()->email(),
"experience_context" => [
"user_action" => "PAY_NOW"
],
],
];
/** If we have a complete address, add it to the order, otherwise leave it blank! */
if(
strlen($this->client->shipping_address1 ?? '') > 2 &&
strlen($this->client->shipping_city ?? '') > 2 &&
strlen($this->client->shipping_state ?? '') >= 2 &&
strlen($this->client->shipping_postal_code ?? '') > 2 &&
strlen($this->client->shipping_country->iso_3166_2 ?? '') >= 2
) {
$order['paypal']['address'] = [
"address_line_1" => $this->client->shipping_address1,
"address_line_2" => $this->client->shipping_address2,
"admin_area_2" => $this->client->shipping_city,
"admin_area_1" => $this->client->shipping_state,
"postal_code" => $this->client->shipping_postal_code,
"country_code" => $this->client->present()->shipping_country_code(),
];
}
elseif(
strlen($this->client->address1 ?? '') > 2 &&
strlen($this->client->city ?? '') > 2 &&
strlen($this->client->state ?? '') >= 2 &&
strlen($this->client->postal_code ?? '') > 2 &&
strlen($this->client->country->iso_3166_2 ?? '') >= 2
)
{
$order['paypal']['address'] = [
"address_line_1" => $this->client->address1,
"address_line_2" => $this->client->address2,
"admin_area_2" => $this->client->city,
"admin_area_1" => $this->client->state,
"postal_code" => $this->client->postal_code,
"country_code" => $this->client->country->iso_3166_2,
];
}
return $order;
}
private function createOrder(array $data): string
{ {
$_invoice = collect($this->payment_hash->data->invoices)->first(); $_invoice = collect($this->payment_hash->data->invoices)->first();
@ -576,126 +250,81 @@ return render('gateways.paypal.pay', $data);
] ]
]; ];
if($shipping = $this->getShippingAddress()) { if($shipping = $this->getShippingAddress()) {
$order['purchase_units'][0]["shipping"] = $shipping; $order['purchase_units'][0]["shipping"] = $shipping;
} }
if(isset($data['payment_source'])) if(isset($data['payment_source']))
$order['payment_source'] = $data['payment_source']; $order['payment_source'] = $data['payment_source'];
$r = $this->gatewayRequest('/v2/checkout/orders', 'post', $order); $r = $this->gatewayRequest('/v2/checkout/orders', 'post', $order);
return $r->json()['id']; return $r->json()['id'];
} }
private function getShippingAddress(): ?array /**
{ * processTokenPayment
return $this->company_gateway->require_shipping_address ? *
[ * With PayPal and token payments, the order needs to be
"address" => * deleted and then created with the payment source that
[ * has been selected by the client.
"address_line_1" => strlen($this->client->shipping_address1) > 1 ? $this->client->shipping_address1 : $this->client->address1, *
"address_line_2" => $this->client->shipping_address2, * This method handle the deletion of the current paypal order,
"admin_area_2" => strlen($this->client->shipping_city) > 1 ? $this->client->shipping_city : $this->client->city, * and the automatic payment of the order with the selected payment source.
"admin_area_1" => strlen($this->client->shipping_state) > 1 ? $this->client->shipping_state : $this->client->state, *
"postal_code" => strlen($this->client->shipping_postal_code) > 1 ? $this->client->shipping_postal_code : $this->client->postal_code, * @param mixed $request
"country_code" => $this->client->present()->shipping_country_code(), * @param array $response
], * @return void
] */
public function processTokenPayment($request, array $response) {
: [ $cgt = ClientGatewayToken::where('client_id', $this->client->id)
"name" => [ ->where('token', $request['token'])
"full_name" => $this->client->present()->name() ->firstOrFail();
]
$orderId = $response['orderID'];
$r = $this->gatewayRequest("/v1/checkout/orders/{$orderId}/", 'delete', ['body' => '']);
$data['amount_with_fee'] = $this->payment_hash->data->amount_with_fee;
$data["payment_source"] = [
"card" => [
"vault_id" => $cgt->token,
"stored_credential" => [
"payment_initiator" => "MERCHANT",
"payment_type" => "UNSCHEDULED",
"usage" => "SUBSEQUENT",
],
],
];
$orderId = $this->createOrder($data);
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderId}", 'get', ['body' => '']);
$response = $r->json();
$data = [
'payment_type' => $this->getPaymentMethod($request->gateway_type_id),
'amount' => $response['purchase_units'][0]['payments']['captures'][0]['amount']['value'],
'transaction_reference' => $response['purchase_units'][0]['payments']['captures'][0]['id'],
'gateway_type_id' => $this->gateway_type_id,
]; ];
} $payment = $this->createPayment($data, \App\Models\Payment::STATUS_COMPLETED);
/**
* Generates the gateway request
*
* @param string $uri
* @param string $verb
* @param array $data
* @param ?array $headers
* @return \Illuminate\Http\Client\Response
*/
public function gatewayRequest(string $uri, string $verb, array $data, ?array $headers = [])
{
$this->init();
$r = Http::withToken($this->access_token)
->withHeaders($this->getHeaders($headers))
->{$verb}("{$this->api_endpoint_url}{$uri}", $data);
if($r->successful()) {
return $r;
}
SystemLogger::dispatch( SystemLogger::dispatch(
['response' => $r->body()], ['response' => $response, 'data' => $data],
SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::EVENT_GATEWAY_SUCCESS,
SystemLog::TYPE_PAYPAL, SystemLog::TYPE_PAYPAL,
$this->client, $this->client,
$this->client->company ?? $this->company_gateway->company, $this->client->company,
); );
throw new PaymentFailed("Gateway failure - {$r->body()}", 401); return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]);
} }
private function getHeaders(array $headers = []): array
{
return array_merge([
'Accept' => 'application/json',
'Content-type' => 'application/json',
'Accept-Language' => 'en_US',
'PayPal-Partner-Attribution-Id' => 'invoiceninja_SP_PPCP',
'PayPal-Request-Id' => Str::uuid()->toString(),
], $headers);
}
private function feeCalc($invoice, $invoice_total)
{
$invoice->service()->removeUnpaidGatewayFees();
$invoice = $invoice->fresh();
$balance = floatval($invoice->balance);
$_updated_invoice = $invoice->service()->addGatewayFee($this->company_gateway, GatewayType::PAYPAL, $invoice_total)->save();
if (floatval($_updated_invoice->balance) > $balance) {
$fee = floatval($_updated_invoice->balance) - $balance;
$this->payment_hash->fee_total = $fee;
$this->payment_hash->save();
return $fee;
}
return 0;
}
public function auth(): bool
{
try {
$this->init()->getClientToken();
return true;
}
catch(\Exception $e) {
}
return false;
}
public function importCustomers()
{
return true;
}
} }

View File

@ -150,7 +150,7 @@ class TaskRepository extends BaseRepository
{ {
if(isset($time_log[0][0])) { if(isset($time_log[0][0])) {
return \Carbon\Carbon::createFromTimestamp($time_log[0][0]); return \Carbon\Carbon::createFromTimestamp($time_log[0][0])->addSeconds($task->company->utc_offset());
} }
return null; return null;

View File

@ -11,10 +11,10 @@
namespace App\Services\EDocument\Standards; namespace App\Services\EDocument\Standards;
use App\DataMapper\InvoiceItem;
use App\Models\Credit; use App\Models\Credit;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Product; use App\Models\Product;
use App\Models\PurchaseOrder;
use App\Models\Quote; use App\Models\Quote;
use App\Services\AbstractService; use App\Services\AbstractService;
use horstoeko\zugferd\codelists\ZugferdDutyTaxFeeCategories; use horstoeko\zugferd\codelists\ZugferdDutyTaxFeeCategories;
@ -56,6 +56,7 @@ class ZugferdEDokument extends AbstractService
->setDocumentSeller($company->getSetting('name')) ->setDocumentSeller($company->getSetting('name'))
->setDocumentSellerAddress($company->getSetting("address1"), $company->getSetting("address2"), "", $company->getSetting("postal_code"), $company->getSetting("city"), $company->country()->iso_3166_2, $company->getSetting("state")) ->setDocumentSellerAddress($company->getSetting("address1"), $company->getSetting("address2"), "", $company->getSetting("postal_code"), $company->getSetting("city"), $company->country()->iso_3166_2, $company->getSetting("state"))
->setDocumentSellerContact($this->document->user->present()->getFullName(), "", $this->document->user->present()->phone(), "", $this->document->user->email) ->setDocumentSellerContact($this->document->user->present()->getFullName(), "", $this->document->user->present()->phone(), "", $this->document->user->email)
->setDocumentSellerCommunication("EM", $this->document->user->email)
->setDocumentBuyer($client->present()->name(), $client->number) ->setDocumentBuyer($client->present()->name(), $client->number)
->setDocumentBuyerAddress($client->address1, "", "", $client->postal_code, $client->city, $client->country->iso_3166_2, $client->state) ->setDocumentBuyerAddress($client->address1, "", "", $client->postal_code, $client->city, $client->country->iso_3166_2, $client->state)
->setDocumentBuyerContact($client->present()->primary_contact_name(), "", $client->present()->phone(), "", $client->present()->email()) ->setDocumentBuyerContact($client->present()->primary_contact_name(), "", $client->present()->phone(), "", $client->present()->email())
@ -71,13 +72,15 @@ class ZugferdEDokument extends AbstractService
// Probably wrong file code https://github.com/horstoeko/zugferd/blob/master/src/codelists/ZugferdInvoiceType.php // Probably wrong file code https://github.com/horstoeko/zugferd/blob/master/src/codelists/ZugferdInvoiceType.php
if (empty($this->document->number)) { if (empty($this->document->number)) {
$this->xdocument->setDocumentInformation("DRAFT", "84", date_create($this->document->date ?? now()->format('Y-m-d')), $client->getCurrencyCode()); $this->xdocument->setDocumentInformation("DRAFT", "84", date_create($this->document->date ?? now()->format('Y-m-d')), $client->getCurrencyCode());
$this->xdocument->setIsTestDocument();
} else { } else {
$this->xdocument->setDocumentInformation($this->document->number, "84", date_create($this->document->date ?? now()->format('Y-m-d')), $client->getCurrencyCode()); $this->xdocument->setDocumentInformation($this->document->number, "84", date_create($this->document->date ?? now()->format('Y-m-d')), $client->getCurrencyCode());
}; }
break; break;
case Invoice::class: case Invoice::class:
if (empty($this->document->number)) { if (empty($this->document->number)) {
$this->xdocument->setDocumentInformation("DRAFT", "380", date_create($this->document->date ?? now()->format('Y-m-d')), $client->getCurrencyCode()); $this->xdocument->setDocumentInformation("DRAFT", "380", date_create($this->document->date ?? now()->format('Y-m-d')), $client->getCurrencyCode());
$this->xdocument->setIsTestDocument();
} else { } else {
$this->xdocument->setDocumentInformation($this->document->number, "380", date_create($this->document->date ?? now()->format('Y-m-d')), $client->getCurrencyCode()); $this->xdocument->setDocumentInformation($this->document->number, "380", date_create($this->document->date ?? now()->format('Y-m-d')), $client->getCurrencyCode());
} }
@ -85,6 +88,7 @@ class ZugferdEDokument extends AbstractService
case Credit::class: case Credit::class:
if (empty($this->document->number)) { if (empty($this->document->number)) {
$this->xdocument->setDocumentInformation("DRAFT", "389", date_create($this->document->date ?? now()->format('Y-m-d')), $client->getCurrencyCode()); $this->xdocument->setDocumentInformation("DRAFT", "389", date_create($this->document->date ?? now()->format('Y-m-d')), $client->getCurrencyCode());
$this->xdocument->setIsTestDocument();
} else { } else {
$this->xdocument->setDocumentInformation($this->document->number, "389", date_create($this->document->date ?? now()->format('Y-m-d')), $client->getCurrencyCode()); $this->xdocument->setDocumentInformation($this->document->number, "389", date_create($this->document->date ?? now()->format('Y-m-d')), $client->getCurrencyCode());
} }
@ -92,11 +96,13 @@ class ZugferdEDokument extends AbstractService
if (isset($this->document->po_number)) { if (isset($this->document->po_number)) {
$this->xdocument->setDocumentBuyerOrderReferencedDocument($this->document->po_number); $this->xdocument->setDocumentBuyerOrderReferencedDocument($this->document->po_number);
} }
if (empty($client->routing_id)) { if (empty($client->routing_id)) {
$this->xdocument->setDocumentBuyerReference(ctrans("texts.xinvoice_no_buyers_reference"));
$this->xdocument->setDocumentBuyerReference(ctrans("texts.xinvoice_no_buyers_reference"))
->setDocumentSellerCommunication("EM", $client->present()->email());
} else { } else {
$this->xdocument->setDocumentBuyerReference($client->routing_id); $this->xdocument->setDocumentBuyerReference($client->routing_id)
->setDocumentBuyerCommunication("0204", $client->routing_id);
} }
if (isset($client->shipping_address1) && $client->shipping_country) { if (isset($client->shipping_address1) && $client->shipping_country) {
$this->xdocument->setDocumentShipToAddress($client->shipping_address1, $client->shipping_address2, "", $client->shipping_postal_code, $client->shipping_city, $client->shipping_country->iso_3166_2, $client->shipping_state); $this->xdocument->setDocumentShipToAddress($client->shipping_address1, $client->shipping_address2, "", $client->shipping_postal_code, $client->shipping_city, $client->shipping_country->iso_3166_2, $client->shipping_state);
@ -113,15 +119,18 @@ class ZugferdEDokument extends AbstractService
$this->xdocument->addDocumentSellerTaxRegistration("FC", $company->getSetting('vat_number')); $this->xdocument->addDocumentSellerTaxRegistration("FC", $company->getSetting('vat_number'));
} else { } else {
$this->xdocument->addDocumentSellerTaxRegistration("VA", $company->getSetting('vat_number')); $this->xdocument->addDocumentSellerTaxRegistration("VA", $company->getSetting('vat_number'));
}
if (!empty($client->vat_number)){
$this->xdocument->addDocumentBuyerTaxRegistration("VA", $client->vat_number);
} }
$invoicing_data = $this->document->calc(); $invoicing_data = $this->document->calc();
//Create line items and calculate taxes //Create line items and calculate taxes
foreach ($this->document->line_items as $index => $item) { foreach ($this->document->line_items as $index => $item) {
/** @var \App\DataMapper\InvoiceItem $item **/ /** @var InvoiceItem $item **/
$this->xdocument->addNewPosition($index) $this->xdocument->addNewPosition($index)
->setDocumentPositionGrossPrice($item->gross_line_total) ->setDocumentPositionGrossPrice($item->gross_line_total+$item->discount)
->setDocumentPositionNetPrice($item->line_total); ->setDocumentPositionNetPrice($item->line_total);
if (!empty($item->product_key)) { if (!empty($item->product_key)) {
if (!empty($item->notes)) { if (!empty($item->notes)) {
@ -141,56 +150,90 @@ class ZugferdEDokument extends AbstractService
} else { } else {
$this->xdocument->setDocumentPositionQuantity($item->quantity, "H87"); $this->xdocument->setDocumentPositionQuantity($item->quantity, "H87");
} }
$linenetamount = $item->line_total; $line_discount = 0.0;
if ($item->discount > 0) { if ($item->discount > 0) {
if ($this->document->is_amount_discount) { if ($this->document->is_amount_discount) {
$linenetamount -= $item->discount; $line_discount -= $item->discount;
} else { } else {
$linenetamount -= $linenetamount * ($item->discount / 100); $line_discount -= $item->line_total * ($item->discount / 100);
} }
$this->xdocument->addDocumentPositionGrossPriceAllowanceCharge( abs($line_discount), false);
} }
$this->xdocument->setDocumentPositionLineSummation($linenetamount);
$this->xdocument->setDocumentPositionLineSummation($item->line_total);
// According to european law, each line item can only have one tax rate // According to european law, each line item can only have one tax rate
if (!(empty($item->tax_name1) && empty($item->tax_name2) && empty($item->tax_name3))) { if (!(empty($item->tax_name1) && empty($item->tax_name2) && empty($item->tax_name3))) {
$taxtype = $this->getTaxType($item->tax_id); $taxtype = $this->getTaxType($item->tax_id);
if (!empty($item->tax_name1)) { if (!empty($item->tax_name1)) {
$this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate1); if ($taxtype == ZugferdDutyTaxFeeCategories::VAT_EXEMPT_FOR_EEA_INTRACOMMUNITY_SUPPLY_OF_GOODS_AND_SERVICES){
$this->addtoTaxMap($taxtype, $linenetamount, $item->tax_rate1); $this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate1, exemptionReason: ctrans('texts.intracommunity_tax_info'));
} else {
$this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate1);
}
$this->addtoTaxMap($taxtype, $item->line_total, $item->tax_rate1);
} elseif (!empty($item->tax_name2)) { } elseif (!empty($item->tax_name2)) {
$this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate2); if ($taxtype == ZugferdDutyTaxFeeCategories::VAT_EXEMPT_FOR_EEA_INTRACOMMUNITY_SUPPLY_OF_GOODS_AND_SERVICES){
$this->addtoTaxMap($taxtype, $linenetamount, $item->tax_rate2); $this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate2, exemptionReason: ctrans('texts.intracommunity_tax_info'));
} else {
$this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate2);
}
$this->addtoTaxMap($taxtype, $item->line_total, $item->tax_rate2);
} elseif (!empty($item->tax_name3)) { } elseif (!empty($item->tax_name3)) {
$this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate3); if ($taxtype == ZugferdDutyTaxFeeCategories::VAT_EXEMPT_FOR_EEA_INTRACOMMUNITY_SUPPLY_OF_GOODS_AND_SERVICES){
$this->addtoTaxMap($taxtype, $linenetamount, $item->tax_rate3); $this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate3, exemptionReason: ctrans('texts.intracommunity_tax_info'));
} else {
$this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate3);
}
$this->addtoTaxMap($taxtype, $item->line_total, $item->tax_rate3);
} else { } else {
// nlog("Can't add correct tax position"); nlog("Can't add correct tax position");
} }
} else { } else {
if (!empty($this->document->tax_name1)) { if (!empty($this->document->tax_name1)) {
$taxtype = $this->getTaxType($this->document->tax_name1); $taxtype = $this->getTaxType($this->document->tax_name1);
$this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $this->document->tax_rate1); $this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $this->document->tax_rate1);
$this->addtoTaxMap($taxtype, $linenetamount, $this->document->tax_rate1); $this->addtoTaxMap($taxtype, $item->line_total, $this->document->tax_rate1);
} elseif (!empty($this->document->tax_name2)) { } elseif (!empty($this->document->tax_name2)) {
$taxtype = $this->getTaxType($this->document->tax_name2); $taxtype = $this->getTaxType($this->document->tax_name2);
$this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $this->document->tax_rate2); $this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $this->document->tax_rate2);
$this->addtoTaxMap($taxtype, $linenetamount, $this->document->tax_rate2); $this->addtoTaxMap($taxtype, $item->line_total, $this->document->tax_rate2);
} elseif (!empty($this->document->tax_name3)) { } elseif (!empty($this->document->tax_name3)) {
$taxtype = $this->getTaxType($this->document->tax_name3); $taxtype = $this->getTaxType($this->document->tax_name3);
$this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $this->document->tax_rate3); $this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $this->document->tax_rate3);
$this->addtoTaxMap($taxtype, $linenetamount, $this->document->tax_rate3); $this->addtoTaxMap($taxtype, $item->line_total, $this->document->tax_rate3);
} else { } else {
$taxtype = ZugferdDutyTaxFeeCategories::ZERO_RATED_GOODS; $taxtype = ZugferdDutyTaxFeeCategories::ZERO_RATED_GOODS;
$this->xdocument->addDocumentPositionTax($taxtype, 'VAT', 0); $this->xdocument->addDocumentPositionTax($taxtype, 'VAT', 0);
$this->addtoTaxMap($taxtype, $linenetamount, 0); $this->addtoTaxMap($taxtype, $item->line_total, 0);
// nlog("Can't add correct tax position"); // nlog("Can't add correct tax position");
} }
} }
} }
if ($this->document->is_amount_discount) {
$document_discount = abs($this->document->discount);
} else {
$document_discount = $this->document->amount * $this->document->discount / 100;
}
$this->xdocument->setDocumentSummation($this->document->amount, $this->document->balance, $invoicing_data->getSubTotal(), $invoicing_data->getTotalSurcharges(), $invoicing_data->getTotalDiscount(), $invoicing_data->getSubTotal(), $invoicing_data->getItemTotalTaxes(), 0.0, $this->document->amount - $this->document->balance); $this->xdocument->setDocumentSummation($this->document->amount, $this->document->balance, $invoicing_data->getSubTotal(), $invoicing_data->getTotalSurcharges(), $document_discount, $invoicing_data->getSubTotal()-$document_discount, $invoicing_data->getItemTotalTaxes(), 0.0, $this->document->amount - $this->document->balance);
foreach ($this->tax_map as $item) { foreach ($this->tax_map as $item) {
if ($document_discount > 0){
if ($item["net_amount"] >= $document_discount) {
$item["net_amount"] -= $document_discount;
$this->xdocument->addDocumentAllowanceCharge($document_discount, false, $item["tax_type"], "VAT", $item["tax_rate"] * 100);
} else {
$document_discount -= $item["net_amount"];
$this->xdocument->addDocumentAllowanceCharge($item["net_amount"], false, $item["tax_type"], "VAT", $item["tax_rate"] * 100);
$item["net_amount"] = 0;
}
}
if ($item["tax_type"] == ZugferdDutyTaxFeeCategories::VAT_EXEMPT_FOR_EEA_INTRACOMMUNITY_SUPPLY_OF_GOODS_AND_SERVICES){
$this->xdocument->addDocumentTax($item["tax_type"], "VAT", $item["net_amount"], $item["tax_rate"] * $item["net_amount"], $item["tax_rate"] * 100, ctrans('texts.intracommunity_tax_info'));
} else {
$this->xdocument->addDocumentTax($item["tax_type"], "VAT", $item["net_amount"], $item["tax_rate"] * $item["net_amount"], $item["tax_rate"] * 100); $this->xdocument->addDocumentTax($item["tax_type"], "VAT", $item["net_amount"], $item["tax_rate"] * $item["net_amount"], $item["tax_rate"] * 100);
}
} }
// The validity can be checked using https://portal3.gefeg.com/invoice/validation or https://e-rechnung.bayern.de/app/#/upload // The validity can be checked using https://portal3.gefeg.com/invoice/validation or https://e-rechnung.bayern.de/app/#/upload

View File

@ -314,7 +314,7 @@ class Email implements ShouldQueue
$this->logMailError($e->getMessage(), $this->company->clients()->first()); $this->logMailError($e->getMessage(), $this->company->clients()->first());
$this->cleanUpMailers(); $this->cleanUpMailers();
$this->entityEmailFailed($message); $this->entityEmailFailed($message);
return; return;
} }

View File

@ -219,6 +219,7 @@ class CompanyTransformer extends EntityTransformer
'smtp_password' => $company->smtp_password ? '********' : '', 'smtp_password' => $company->smtp_password ? '********' : '',
'smtp_local_domain' => (string) $company->smtp_local_domain ?? '', 'smtp_local_domain' => (string) $company->smtp_local_domain ?? '',
'smtp_verify_peer' => (bool) $company->smtp_verify_peer, 'smtp_verify_peer' => (bool) $company->smtp_verify_peer,
'e_invoice' => $company->e_invoice ?: new \stdClass(),
]; ];
} }

View File

@ -133,6 +133,7 @@ class CreditTransformer extends EntityTransformer
'subscription_id' => $this->encodePrimaryKey($credit->subscription_id), 'subscription_id' => $this->encodePrimaryKey($credit->subscription_id),
'invoice_id' => $credit->invoice_id ? $this->encodePrimaryKey($credit->invoice_id) : '', 'invoice_id' => $credit->invoice_id ? $this->encodePrimaryKey($credit->invoice_id) : '',
'tax_info' => $credit->tax_data ?: new \stdClass(), 'tax_info' => $credit->tax_data ?: new \stdClass(),
'e_invoice' => $credit->e_invoice ?: new \stdClass(),
]; ];
} }

View File

@ -148,6 +148,8 @@ class ExpenseTransformer extends EntityTransformer
'uses_inclusive_taxes' => (bool) $expense->uses_inclusive_taxes, 'uses_inclusive_taxes' => (bool) $expense->uses_inclusive_taxes,
'calculate_tax_by_amount' => (bool) $expense->calculate_tax_by_amount, 'calculate_tax_by_amount' => (bool) $expense->calculate_tax_by_amount,
'entity_type' => 'expense', 'entity_type' => 'expense',
'e_invoice' => $expense->e_invoice ?: new \stdClass(),
]; ];
} }
} }

View File

@ -158,6 +158,8 @@ class InvoiceTransformer extends EntityTransformer
'subscription_id' => $this->encodePrimaryKey($invoice->subscription_id), 'subscription_id' => $this->encodePrimaryKey($invoice->subscription_id),
'auto_bill_enabled' => (bool) $invoice->auto_bill_enabled, 'auto_bill_enabled' => (bool) $invoice->auto_bill_enabled,
'tax_info' => $invoice->tax_data ?: new \stdClass(), 'tax_info' => $invoice->tax_data ?: new \stdClass(),
'e_invoice' => $invoice->e_invoice ?: new \stdClass(),
]; ];
if (request()->has('reminder_schedule') && request()->query('reminder_schedule') == 'true') { if (request()->has('reminder_schedule') && request()->query('reminder_schedule') == 'true') {

View File

@ -150,6 +150,8 @@ class PurchaseOrderTransformer extends EntityTransformer
'expense_id' => $this->encodePrimaryKey($purchase_order->expense_id), 'expense_id' => $this->encodePrimaryKey($purchase_order->expense_id),
'currency_id' => $purchase_order->currency_id ? (string) $purchase_order->currency_id : '', 'currency_id' => $purchase_order->currency_id ? (string) $purchase_order->currency_id : '',
'tax_info' => $purchase_order->tax_data ?: new \stdClass(), 'tax_info' => $purchase_order->tax_data ?: new \stdClass(),
'e_invoice' => $purchase_order->e_invoice ?: new \stdClass(),
]; ];
} }
} }

View File

@ -149,6 +149,8 @@ class QuoteTransformer extends EntityTransformer
'project_id' => $this->encodePrimaryKey($quote->project_id), 'project_id' => $this->encodePrimaryKey($quote->project_id),
'subscription_id' => $this->encodePrimaryKey($quote->subscription_id), 'subscription_id' => $this->encodePrimaryKey($quote->subscription_id),
'tax_info' => $quote->tax_data ?: new \stdClass(), 'tax_info' => $quote->tax_data ?: new \stdClass(),
'e_invoice' => $quote->e_invoice ?: new \stdClass(),
]; ];
} }
} }

View File

@ -561,10 +561,19 @@ class HtmlEngine
$data['$spc_qr_code'] = ['value' => $this->company->present()->getSpcQrCode($this->client->currency()->code, $this->entity->number, $this->entity->balance, $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'company1', $this->settings->custom_value1, $this->client)), 'label' => '']; $data['$spc_qr_code'] = ['value' => $this->company->present()->getSpcQrCode($this->client->currency()->code, $this->entity->number, $this->entity->balance, $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'company1', $this->settings->custom_value1, $this->client)), 'label' => ''];
$logo = $this->company->present()->logo_base64($this->settings); if(Ninja::isHosted())
$logo = $this->company->present()->logo($this->settings);
else
$logo = $this->company->present()->logo_base64($this->settings);
$logo_url = $this->company->present()->logo($this->settings);
$data['$company.logo'] = ['value' => $logo ?: ' ', 'label' => ctrans('texts.logo')]; $data['$company.logo'] = ['value' => $logo ?: ' ', 'label' => ctrans('texts.logo')];
$data['$company_logo'] = &$data['$company.logo']; $data['$company_logo'] = &$data['$company.logo'];
$data['$company.logo_url'] = ['value' => $logo_url ?: ' ', 'label' => ctrans('texts.logo')];
$data['$company1'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'company1', $this->settings->custom_value1, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'company1')]; $data['$company1'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'company1', $this->settings->custom_value1, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'company1')];
$data['$company2'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'company2', $this->settings->custom_value2, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'company2')]; $data['$company2'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'company2', $this->settings->custom_value2, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'company2')];
$data['$company3'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'company3', $this->settings->custom_value3, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'company3')]; $data['$company3'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'company3', $this->settings->custom_value3, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'company3')];

44
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "da485c7cec773404ffe59d450b6505cf", "content-hash": "1356155e46e797b140685c105df97b8e",
"packages": [ "packages": [
{ {
"name": "adrienrn/php-mimetyper", "name": "adrienrn/php-mimetyper",
@ -3221,26 +3221,26 @@
}, },
{ {
"name": "firebase/php-jwt", "name": "firebase/php-jwt",
"version": "v6.10.0", "version": "v6.10.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/firebase/php-jwt.git", "url": "https://github.com/firebase/php-jwt.git",
"reference": "a49db6f0a5033aef5143295342f1c95521b075ff" "reference": "500501c2ce893c824c801da135d02661199f60c5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/a49db6f0a5033aef5143295342f1c95521b075ff", "url": "https://api.github.com/repos/firebase/php-jwt/zipball/500501c2ce893c824c801da135d02661199f60c5",
"reference": "a49db6f0a5033aef5143295342f1c95521b075ff", "reference": "500501c2ce893c824c801da135d02661199f60c5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.4||^8.0" "php": "^8.0"
}, },
"require-dev": { "require-dev": {
"guzzlehttp/guzzle": "^6.5||^7.4", "guzzlehttp/guzzle": "^7.4",
"phpspec/prophecy-phpunit": "^2.0", "phpspec/prophecy-phpunit": "^2.0",
"phpunit/phpunit": "^9.5", "phpunit/phpunit": "^9.5",
"psr/cache": "^1.0||^2.0", "psr/cache": "^2.0||^3.0",
"psr/http-client": "^1.0", "psr/http-client": "^1.0",
"psr/http-factory": "^1.0" "psr/http-factory": "^1.0"
}, },
@ -3278,9 +3278,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/firebase/php-jwt/issues", "issues": "https://github.com/firebase/php-jwt/issues",
"source": "https://github.com/firebase/php-jwt/tree/v6.10.0" "source": "https://github.com/firebase/php-jwt/tree/v6.10.1"
}, },
"time": "2023-12-01T16:26:39+00:00" "time": "2024-05-18T18:05:11+00:00"
}, },
{ {
"name": "fruitcake/php-cors", "name": "fruitcake/php-cors",
@ -3602,23 +3602,23 @@
}, },
{ {
"name": "google/apiclient-services", "name": "google/apiclient-services",
"version": "v0.355.0", "version": "v0.356.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/googleapis/google-api-php-client-services.git", "url": "https://github.com/googleapis/google-api-php-client-services.git",
"reference": "235e6a45ecafd77accc102b5ab6d529aab54da23" "reference": "8e22b0a6f661f2db3f99abb6ee5a1dcf28d370e7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/235e6a45ecafd77accc102b5ab6d529aab54da23", "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/8e22b0a6f661f2db3f99abb6ee5a1dcf28d370e7",
"reference": "235e6a45ecafd77accc102b5ab6d529aab54da23", "reference": "8e22b0a6f661f2db3f99abb6ee5a1dcf28d370e7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.4||^8.0" "php": "^8.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^5.7||^8.5.13" "phpunit/phpunit": "^9.6"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@ -3640,9 +3640,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/googleapis/google-api-php-client-services/issues", "issues": "https://github.com/googleapis/google-api-php-client-services/issues",
"source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.355.0" "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.356.0"
}, },
"time": "2024-05-11T01:02:11+00:00" "time": "2024-05-18T01:10:18+00:00"
}, },
{ {
"name": "google/auth", "name": "google/auth",
@ -5034,12 +5034,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/invoiceninja/einvoice.git", "url": "https://github.com/invoiceninja/einvoice.git",
"reference": "6028038ff94e6c0090ba5c444bd0be56a65bc0bc" "reference": "39aec367c528ba66d923dc1d9e5c96f673bb46c7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/invoiceninja/einvoice/zipball/6028038ff94e6c0090ba5c444bd0be56a65bc0bc", "url": "https://api.github.com/repos/invoiceninja/einvoice/zipball/39aec367c528ba66d923dc1d9e5c96f673bb46c7",
"reference": "6028038ff94e6c0090ba5c444bd0be56a65bc0bc", "reference": "39aec367c528ba66d923dc1d9e5c96f673bb46c7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5075,7 +5075,7 @@
"source": "https://github.com/invoiceninja/einvoice/tree/main", "source": "https://github.com/invoiceninja/einvoice/tree/main",
"issues": "https://github.com/invoiceninja/einvoice/issues" "issues": "https://github.com/invoiceninja/einvoice/issues"
}, },
"time": "2024-05-18T12:35:18+00:00" "time": "2024-05-20T11:42:32+00:00"
}, },
{ {
"name": "invoiceninja/inspector", "name": "invoiceninja/inspector",

View File

@ -27,6 +27,7 @@ class AccountFactory extends Factory
'default_company_id' => 1, 'default_company_id' => 1,
'key' => Str::random(32), 'key' => Str::random(32),
'report_errors' => 1, 'report_errors' => 1,
'referral_code' => Str::lower(Str::random(32)),
]; ];
} }
} }

View File

@ -12,24 +12,28 @@ return new class extends Migration
*/ */
public function up(): void public function up(): void
{ {
$gateway = new Gateway; if(!Gateway::find(62))
$gateway->name = 'BTCPay'; {
$gateway->key = 'vpyfbmdrkqcicpkjqdusgjfluebftuva'; $gateway = new Gateway;
$gateway->provider = 'BTCPay'; $gateway->id = 62;
$gateway->is_offsite = true; $gateway->name = 'BTCPay';
$gateway->key = 'vpyfbmdrkqcicpkjqdusgjfluebftuva';
$gateway->provider = 'BTCPay';
$gateway->is_offsite = true;
$btcpayFieds = new \stdClass; $btcpayFieds = new \stdClass;
$btcpayFieds->btcpayUrl = ""; $btcpayFieds->btcpayUrl = "";
$btcpayFieds->apiKey = ""; $btcpayFieds->apiKey = "";
$btcpayFieds->storeId = ""; $btcpayFieds->storeId = "";
$btcpayFieds->webhookSecret = ""; $btcpayFieds->webhookSecret = "";
$gateway->fields = \json_encode($btcpayFieds); $gateway->fields = \json_encode($btcpayFieds);
$gateway->visible = true; $gateway->visible = true;
$gateway->site_url = 'https://btcpayserver.org'; $gateway->site_url = 'https://btcpayserver.org';
$gateway->default_gateway_type_id = GatewayType::CRYPTO; $gateway->default_gateway_type_id = GatewayType::CRYPTO;
$gateway->save(); $gateway->save();
}
} }
/** /**
@ -39,4 +43,4 @@ return new class extends Migration
{ {
// //
} }
}; };

View File

@ -0,0 +1,53 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('companies', function (Blueprint $table) {
$table->mediumText('e_invoice')->nullable();
});
Schema::table('invoices', function (Blueprint $table) {
$table->mediumText('e_invoice')->nullable();
});
Schema::table('quotes', function (Blueprint $table) {
$table->mediumText('e_invoice')->nullable();
});
Schema::table('credits', function (Blueprint $table) {
$table->mediumText('e_invoice')->nullable();
});
Schema::table('purchase_orders', function (Blueprint $table) {
$table->mediumText('e_invoice')->nullable();
});
Schema::table('expenses', function (Blueprint $table) {
$table->mediumText('e_invoice')->nullable();
});
Schema::table('accounts', function (Blueprint $table) {
$table->integer('email_quota')->default(20)->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
//
}
};

View File

@ -1,4 +1,5 @@
<?php <?php
/** /**
* Invoice Ninja (https://invoiceninja.com). * Invoice Ninja (https://invoiceninja.com).
* *
@ -8,6 +9,7 @@
* *
* @license https://www.elastic.co/licensing/elastic-license * @license https://www.elastic.co/licensing/elastic-license
*/ */
namespace Database\Seeders; namespace Database\Seeders;
use App\Models\Gateway; use App\Models\Gateway;
@ -85,12 +87,13 @@ class PaymentLibrariesSeeder extends Seeder
['id' => 59, 'name' => 'Forte', 'provider' => 'Forte', 'is_offsite' => false, 'sort_order' => 21, 'key' => 'kivcvjexxvdiyqtj3mju5d6yhpeht2xs', 'fields' => '{"testMode":false,"apiLoginId":"","apiAccessId":"","secureKey":"","authOrganizationId":"","organizationId":"","locationId":""}'], ['id' => 59, 'name' => 'Forte', 'provider' => 'Forte', 'is_offsite' => false, 'sort_order' => 21, 'key' => 'kivcvjexxvdiyqtj3mju5d6yhpeht2xs', 'fields' => '{"testMode":false,"apiLoginId":"","apiAccessId":"","secureKey":"","authOrganizationId":"","organizationId":"","locationId":""}'],
['id' => 60, 'name' => 'PayPal REST', 'provider' => 'PayPal_Rest', 'key' => '80af24a6a691230bbec33e930ab40665', 'fields' => '{"clientId":"","secret":"","signature":"","testMode":false}'], ['id' => 60, 'name' => 'PayPal REST', 'provider' => 'PayPal_Rest', 'key' => '80af24a6a691230bbec33e930ab40665', 'fields' => '{"clientId":"","secret":"","signature":"","testMode":false}'],
['id' => 61, 'name' => 'PayPal Platform', 'provider' => 'PayPal_PPCP', 'key' => '80af24a6a691230bbec33e930ab40666', 'fields' => '{"testMode":false}'], ['id' => 61, 'name' => 'PayPal Platform', 'provider' => 'PayPal_PPCP', 'key' => '80af24a6a691230bbec33e930ab40666', 'fields' => '{"testMode":false}'],
['id' => 62, 'name' => 'BTCPay', 'provider' => 'BTCPay', 'key' => 'vpyfbmdrkqcicpkjqdusgjfluebftuva', 'fields' => '{"btcpayUrl":"", "apiKey:"", "storeId":"", "webhookSecret":""}'],
]; ];
foreach ($gateways as $gateway) { foreach ($gateways as $gateway) {
$record = Gateway::whereName($gateway['name']) $record = Gateway::whereName($gateway['name'])
->whereProvider($gateway['provider']) ->whereProvider($gateway['provider'])
->first(); ->first();
if ($record) { if ($record) {
$record->fill($gateway); $record->fill($gateway);
$record->save(); $record->save();
@ -101,13 +104,13 @@ class PaymentLibrariesSeeder extends Seeder
Gateway::query()->update(['visible' => 0]); Gateway::query()->update(['visible' => 0]);
Gateway::whereIn('id', [1,3,7,11,15,20,39,46,55,50,57,52,58,59,60])->update(['visible' => 1]); Gateway::whereIn('id', [1, 3, 7, 11, 15, 20, 39, 46, 55, 50, 57, 52, 58, 59, 60, 62])->update(['visible' => 1]);
if (Ninja::isHosted()) { if (Ninja::isHosted()) {
Gateway::whereIn('id', [20,49])->update(['visible' => 0]); Gateway::whereIn('id', [20, 49])->update(['visible' => 0]);
Gateway::whereIn('id', [56,61])->update(['visible' => 1]); Gateway::whereIn('id', [56, 61])->update(['visible' => 1]);
} }
Gateway::all()->each(function ($gateway) { Gateway::all()->each(function ($gateway) {
$gateway->site_url = $gateway->getHelp(); $gateway->site_url = $gateway->getHelp();
$gateway->save(); $gateway->save();

View File

@ -252,7 +252,7 @@ class RandomDataSeeder extends Seeder
$invoice->service()->createInvitations()->markSent()->save(); $invoice->service()->createInvitations()->markSent()->save();
$invoice->ledger()->updateInvoiceBalance($invoice->balance); $invoice->ledger()->update_invoiceBalance($invoice->balance);
if (rand(0, 1)) { if (rand(0, 1)) {
$payment = Payment::create([ $payment = Payment::create([
@ -277,7 +277,7 @@ class RandomDataSeeder extends Seeder
event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars())); event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars()));
// $payment->service()->updateInvoicePayment($payment_hash); // $payment->service()->update_invoicePayment($payment_hash);
} }
}); });

View File

@ -5322,6 +5322,11 @@ $lang = array(
'task_round_to_nearest' => 'Round To Nearest', 'task_round_to_nearest' => 'Round To Nearest',
'bulk_updated' => 'Successfully updated data', 'bulk_updated' => 'Successfully updated data',
'bulk_update' => 'Bulk Update', 'bulk_update' => 'Bulk Update',
'calculate' => 'Calculate',
'sum' => 'Sum',
'money' => 'Money',
'web_app' => 'Web App',
'desktop_app' => 'Desktop App',
); );
return $lang; return $lang;

View File

@ -5297,6 +5297,26 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'local_domain_help' => 'Domaine EHLO (facultatif)', 'local_domain_help' => 'Domaine EHLO (facultatif)',
'port_help' => 'ex. 25,587,465', 'port_help' => 'ex. 25,587,465',
'host_help' => 'ex. smtp.gmail.com', 'host_help' => 'ex. smtp.gmail.com',
'always_show_required_fields' => 'Permet l\'affichage des champs requis d\'un formulaire',
'always_show_required_fields_help' => 'Affiche toujours les champs requis d\'un formulaire au paiement',
'advanced_cards' => 'Cartes avancées',
'activity_140' => 'État de compte envoyé à :client',
'invoice_net_amount' => 'Montant net de la facture',
'round_to_minutes' => 'Arrondir aux minutes',
'1_minute' => '1 minute',
'5_minutes' => '5 minutes',
'15_minutes' => '15 minutes',
'30_minutes' => '30 minutes',
'1_hour' => '1 heure',
'1_day' => '1 jour',
'round_tasks' => 'Arrondir les tâches',
'round_tasks_help' => 'Arrondir les intervales à la sauvegarde des tâches',
'direction' => 'Direction',
'round_up' => 'Arrondir à hausse',
'round_down' => 'Arrondir à la baisse',
'task_round_to_nearest' => 'Arrondir au plus près',
'bulk_updated' => 'Les données ont été mises à jour',
'bulk_update' => 'Mise à jour groupée',
); );
return $lang; return $lang;

View File

@ -700,7 +700,7 @@ $lang = array(
'total_invoiced' => 'Total Invoiced', 'total_invoiced' => 'Total Invoiced',
'open_balance' => 'Open Balance', 'open_balance' => 'Open Balance',
'verify_email' => 'Please visit the link in the account confirmation email to verify your email address.', 'verify_email' => 'Please visit the link in the account confirmation email to verify your email address.',
'basic_settings' => 'Basic Settings', 'basic_settings' => '基本設定',
'pro' => 'Pro', 'pro' => 'Pro',
'gateways' => 'ペイメントゲートウェイ', 'gateways' => 'ペイメントゲートウェイ',
'next_send_on' => 'Send Next: :date', 'next_send_on' => 'Send Next: :date',
@ -1344,7 +1344,7 @@ $lang = array(
'auto_bill_payment_method_credit_card' => 'クレジットカード', 'auto_bill_payment_method_credit_card' => 'クレジットカード',
'auto_bill_payment_method_paypal' => 'PayPal アカウント', 'auto_bill_payment_method_paypal' => 'PayPal アカウント',
'auto_bill_notification_placeholder' => 'この請求書は、期日にて登録されているクレジットカードに自動的に請求されます。', 'auto_bill_notification_placeholder' => 'この請求書は、期日にて登録されているクレジットカードに自動的に請求されます。',
'payment_settings' => 'Payment Settings', 'payment_settings' => '支払い設定',
'on_send_date' => '発送日', 'on_send_date' => '発送日',
'on_due_date' => '支払期日', 'on_due_date' => '支払期日',
@ -5300,6 +5300,26 @@ $lang = array(
'local_domain_help' => 'EHLO domain (optional)', 'local_domain_help' => 'EHLO domain (optional)',
'port_help' => 'ie. 25,587,465', 'port_help' => 'ie. 25,587,465',
'host_help' => 'ie. smtp.gmail.com', 'host_help' => 'ie. smtp.gmail.com',
'always_show_required_fields' => 'Allows show required fields form',
'always_show_required_fields_help' => 'Displays the required fields form always at checkout',
'advanced_cards' => 'Advanced Cards',
'activity_140' => 'Statement sent to :client',
'invoice_net_amount' => 'Invoice Net Amount',
'round_to_minutes' => 'Round To Minutes',
'1_minute' => '1 Minute',
'5_minutes' => '5 Minutes',
'15_minutes' => '15 Minutes',
'30_minutes' => '30 Minutes',
'1_hour' => '1 Hour',
'1_day' => '1 Day',
'round_tasks' => 'Round Tasks',
'round_tasks_help' => 'Round time intervals when saving tasks',
'direction' => 'Direction',
'round_up' => 'Round Up',
'round_down' => 'Round Down',
'task_round_to_nearest' => 'Round To Nearest',
'bulk_updated' => 'Successfully updated data',
'bulk_update' => 'Bulk Update',
); );
return $lang; return $lang;

File diff suppressed because one or more lines are too long

View File

@ -9,7 +9,7 @@
] ]
}, },
"resources/js/app.js": { "resources/js/app.js": {
"file": "assets/app-bfac6a32.js", "file": "assets/app-a52d5f77.js",
"imports": [ "imports": [
"_index-08e160a7.js", "_index-08e160a7.js",
"__commonjsHelpers-725317a4.js" "__commonjsHelpers-725317a4.js"

View File

@ -3,313 +3,313 @@ const MANIFEST = 'flutter-app-manifest';
const TEMP = 'flutter-temp-cache'; const TEMP = 'flutter-temp-cache';
const CACHE_NAME = 'flutter-app-cache'; const CACHE_NAME = 'flutter-app-cache';
const RESOURCES = {"canvaskit/canvaskit.js": "c86fbd9e7b17accae76e5ad116583dc4", const RESOURCES = {"canvaskit/skwasm.worker.js": "bfb704a6c714a75da9ef320991e88b03",
"canvaskit/skwasm.worker.js": "bfb704a6c714a75da9ef320991e88b03", "canvaskit/skwasm.js": "445e9e400085faead4493be2224d95aa",
"canvaskit/skwasm.js.symbols": "741d50ffba71f89345996b0aa8426af8",
"canvaskit/canvaskit.wasm": "3d2a2d663e8c5111ac61a46367f751ac", "canvaskit/canvaskit.wasm": "3d2a2d663e8c5111ac61a46367f751ac",
"canvaskit/chromium/canvaskit.js": "43787ac5098c648979c27c13c6f804c3", "canvaskit/canvaskit.js.symbols": "38cba9233b92472a36ff011dc21c2c9f",
"canvaskit/skwasm.js.symbols": "741d50ffba71f89345996b0aa8426af8",
"canvaskit/skwasm.wasm": "e42815763c5d05bba43f9d0337fa7d84",
"canvaskit/canvaskit.js": "c86fbd9e7b17accae76e5ad116583dc4",
"canvaskit/chromium/canvaskit.wasm": "f5934e694f12929ed56a671617acd254", "canvaskit/chromium/canvaskit.wasm": "f5934e694f12929ed56a671617acd254",
"canvaskit/chromium/canvaskit.js.symbols": "4525682ef039faeb11f24f37436dca06", "canvaskit/chromium/canvaskit.js.symbols": "4525682ef039faeb11f24f37436dca06",
"canvaskit/skwasm.js": "445e9e400085faead4493be2224d95aa", "canvaskit/chromium/canvaskit.js": "43787ac5098c648979c27c13c6f804c3",
"canvaskit/skwasm.wasm": "e42815763c5d05bba43f9d0337fa7d84", "icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
"canvaskit/canvaskit.js.symbols": "38cba9233b92472a36ff011dc21c2c9f", "icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
"manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40", "manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40",
"flutter.js": "c71a09214cb6f5f8996a531350400a9a",
"favicon.ico": "51636d3a390451561744c42188ccd628",
"/": "6da89ef00decd8861b95827eacf0294f",
"assets/FontManifest.json": "087fb858dc3cbfbf6baf6a30004922f1",
"assets/AssetManifest.bin": "bf3be26e7055ad9a32f66b3a56138224",
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "3759b2f7a51e83c64a58cfe07b96a8ee",
"assets/packages/intl_phone_field/assets/flags/mh.png": "18dda388ef5c1cf37cae5e7d5fef39bc",
"assets/packages/intl_phone_field/assets/flags/ck.png": "39f343868a8dc8ca95d27b27a5caf480",
"assets/packages/intl_phone_field/assets/flags/fm.png": "d571b8bc4b80980a81a5edbde788b6d2",
"assets/packages/intl_phone_field/assets/flags/cx.png": "8efa3231c8a3900a78f2b51d829f8c52",
"assets/packages/intl_phone_field/assets/flags/tv.png": "c57025ed7ae482210f29b9da86b0d211",
"assets/packages/intl_phone_field/assets/flags/dk.png": "abcd01bdbcc02b4a29cbac237f29cd1d",
"assets/packages/intl_phone_field/assets/flags/jm.png": "074400103847c56c37425a73f9d23665",
"assets/packages/intl_phone_field/assets/flags/bz.png": "fd2d7d27a5ddabe4eb9a10b1d3a433e4",
"assets/packages/intl_phone_field/assets/flags/mp.png": "87351c30a529071ee9a4bb67765fea4f",
"assets/packages/intl_phone_field/assets/flags/hu.png": "281582a753e643b46bdd894047db08bb",
"assets/packages/intl_phone_field/assets/flags/dm.png": "8886b222ed9ccd00f67e8bcf86dadcc2",
"assets/packages/intl_phone_field/assets/flags/mf.png": "134bee9f9d794dc5c0922d1b9bdbb710",
"assets/packages/intl_phone_field/assets/flags/dz.png": "132ceca353a95c8214676b2e94ecd40f",
"assets/packages/intl_phone_field/assets/flags/ca.png": "76f2fac1d3b2cc52ba6695c2e2941632",
"assets/packages/intl_phone_field/assets/flags/gt.png": "706a0c3b5e0b589c843e2539e813839e",
"assets/packages/intl_phone_field/assets/flags/at.png": "570c070177a5ea0fe03e20107ebf5283",
"assets/packages/intl_phone_field/assets/flags/rs.png": "9dff535d2d08c504be63062f39eff0b7",
"assets/packages/intl_phone_field/assets/flags/si.png": "24237e53b34752554915e71e346bb405",
"assets/packages/intl_phone_field/assets/flags/pa.png": "78e3e4fd56f0064837098fe3f22fb41b",
"assets/packages/intl_phone_field/assets/flags/ml.png": "0c50dfd539e87bb4313da0d4556e2d13",
"assets/packages/intl_phone_field/assets/flags/ai.png": "ce5e91ed1725f0499b9231b69a7fd448",
"assets/packages/intl_phone_field/assets/flags/ng.png": "aedbe364bd1543832e88e64b5817e877",
"assets/packages/intl_phone_field/assets/flags/gb-nir.png": "98773db151c150cabe845183241bfe6b",
"assets/packages/intl_phone_field/assets/flags/lr.png": "b92c75e18dd97349c75d6a43bd17ee94",
"assets/packages/intl_phone_field/assets/flags/uz.png": "3adad3bac322220cac8abc1c7cbaacac",
"assets/packages/intl_phone_field/assets/flags/gb-sct.png": "75106a5e49e3e16da76cb33bdac102ab",
"assets/packages/intl_phone_field/assets/flags/mm.png": "32e5293d6029d8294c7dfc3c3835c222",
"assets/packages/intl_phone_field/assets/flags/bm.png": "b366ba84cbc8286c830f392bb9086be5",
"assets/packages/intl_phone_field/assets/flags/cl.png": "6735e0e2d88c119e9ed1533be5249ef1",
"assets/packages/intl_phone_field/assets/flags/lt.png": "7df2cd6566725685f7feb2051f916a3e",
"assets/packages/intl_phone_field/assets/flags/so.png": "1ce20d052f9d057250be96f42647513b",
"assets/packages/intl_phone_field/assets/flags/rw.png": "d1aae0647a5b1ab977ae43ab894ce2c3",
"assets/packages/intl_phone_field/assets/flags/sm.png": "a8d6801cb7c5360e18f0a2ed146b396d",
"assets/packages/intl_phone_field/assets/flags/sr.png": "9f912879f2829a625436ccd15e643e39",
"assets/packages/intl_phone_field/assets/flags/cm.png": "42d52fa71e8b4dbb182ff431749e8d0d",
"assets/packages/intl_phone_field/assets/flags/gf.png": "134bee9f9d794dc5c0922d1b9bdbb710",
"assets/packages/intl_phone_field/assets/flags/dj.png": "078bd37d41f746c3cb2d84c1e9611c55",
"assets/packages/intl_phone_field/assets/flags/pe.png": "4d9249aab70a26fadabb14380b3b55d2",
"assets/packages/intl_phone_field/assets/flags/hm.png": "72be14316f0af3903cdca7a726c0c589",
"assets/packages/intl_phone_field/assets/flags/az.png": "6ffa766f6883d2d3d350cdc22a062ca3",
"assets/packages/intl_phone_field/assets/flags/qa.png": "eb9b3388e554cf85aea1e739247548df",
"assets/packages/intl_phone_field/assets/flags/sc.png": "e969fd5afb1eb5902675b6bcf49a8c2e",
"assets/packages/intl_phone_field/assets/flags/mo.png": "849848a26bbfc87024017418ad7a6233",
"assets/packages/intl_phone_field/assets/flags/im.png": "7c9ccb825f0fca557d795c4330cf4f50",
"assets/packages/intl_phone_field/assets/flags/kr.png": "a3b7da3b76b20a70e9cd63cc2315b51b",
"assets/packages/intl_phone_field/assets/flags/ht.png": "630f7f8567d87409a32955107ad11a86",
"assets/packages/intl_phone_field/assets/flags/md.png": "8911d3d821b95b00abbba8771e997eb3",
"assets/packages/intl_phone_field/assets/flags/bs.png": "2b9540c4fa514f71911a48de0bd77e71",
"assets/packages/intl_phone_field/assets/flags/as.png": "d9c1da515c6f945c2e2554592a9dfaae",
"assets/packages/intl_phone_field/assets/flags/lv.png": "53105fea0cc9cc554e0ceaabc53a2d5d",
"assets/packages/intl_phone_field/assets/flags/ke.png": "cf5aae3699d3cacb39db9803edae172b",
"assets/packages/intl_phone_field/assets/flags/pr.png": "b97b2f4432c430bc340d893f36527e31",
"assets/packages/intl_phone_field/assets/flags/tm.png": "0980fb40ec450f70896f2c588510f933",
"assets/packages/intl_phone_field/assets/flags/mr.png": "f2a62602d43a1ee14625af165b96ce2f",
"assets/packages/intl_phone_field/assets/flags/is.png": "907840430252c431518005b562707831",
"assets/packages/intl_phone_field/assets/flags/ls.png": "2bca756f9313957347404557acb532b0",
"assets/packages/intl_phone_field/assets/flags/af.png": "ba710b50a060b5351381b55366396c30",
"assets/packages/intl_phone_field/assets/flags/sy.png": "24186a0f4ce804a16c91592db5a16a3a",
"assets/packages/intl_phone_field/assets/flags/au.png": "72be14316f0af3903cdca7a726c0c589",
"assets/packages/intl_phone_field/assets/flags/mn.png": "16086e8d89c9067d29fd0f2ea7021a45",
"assets/packages/intl_phone_field/assets/flags/mu.png": "c5228d1e94501d846b5bf203f038ae49",
"assets/packages/intl_phone_field/assets/flags/ve.png": "893391d65cbd10ca787a73578c77d3a7",
"assets/packages/intl_phone_field/assets/flags/mz.png": "1ab1ac750fbbb453d33e9f25850ac2a0",
"assets/packages/intl_phone_field/assets/flags/hr.png": "69711b2ea009a3e7c40045b538768d4e",
"assets/packages/intl_phone_field/assets/flags/jo.png": "c01cb41f74f9db0cf07ba20f0af83011",
"assets/packages/intl_phone_field/assets/flags/ne.png": "a20724c177e86d6a27143aa9c9664a6f",
"assets/packages/intl_phone_field/assets/flags/uy.png": "da4247b21fcbd9e30dc2b3f7c5dccb64",
"assets/packages/intl_phone_field/assets/flags/cd.png": "5b5f832ed6cd9f9240cb31229d8763dc",
"assets/packages/intl_phone_field/assets/flags/bn.png": "ed650de06fff61ff27ec92a872197948",
"assets/packages/intl_phone_field/assets/flags/mc.png": "90c2ad7f144d73d4650cbea9dd621275",
"assets/packages/intl_phone_field/assets/flags/sb.png": "296ecedbd8d1c2a6422c3ba8e5cd54bd",
"assets/packages/intl_phone_field/assets/flags/tz.png": "56ec99c7e0f68b88a2210620d873683a",
"assets/packages/intl_phone_field/assets/flags/nz.png": "65c811e96eb6c9da65538f899c110895",
"assets/packages/intl_phone_field/assets/flags/bf.png": "63f1c67fca7ce8b52b3418a90af6ad37",
"assets/packages/intl_phone_field/assets/flags/gr.png": "ec11281d7decbf07b81a23a72a609b59",
"assets/packages/intl_phone_field/assets/flags/bw.png": "fac8b90d7404728c08686dc39bab4fb3",
"assets/packages/intl_phone_field/assets/flags/sl.png": "61b9d992c8a6a83abc4d432069617811",
"assets/packages/intl_phone_field/assets/flags/nf.png": "1c2069b299ce3660a2a95ec574dfde25",
"assets/packages/intl_phone_field/assets/flags/mg.png": "0ef6271ad284ebc0069ff0aeb5a3ad1e",
"assets/packages/intl_phone_field/assets/flags/vg.png": "fc095e11f5b58604d6f4d3c2b43d167f",
"assets/packages/intl_phone_field/assets/flags/gb-wls.png": "d7d7c77c72cd425d993bdc50720f4d04",
"assets/packages/intl_phone_field/assets/flags/za.png": "b28280c6c3eb4624c18b5455d4a1b1ff",
"assets/packages/intl_phone_field/assets/flags/cf.png": "263583ffdf7a888ce4fba8487d1da0b2",
"assets/packages/intl_phone_field/assets/flags/bh.png": "a1acd86ef0e19ea5f0297bbe1de6cfd4",
"assets/packages/intl_phone_field/assets/flags/iq.png": "bc3e6f68c5188dbf99b473e2bea066f2",
"assets/packages/intl_phone_field/assets/flags/nl.png": "3649c177693bfee9c2fcc63c191a51f1",
"assets/packages/intl_phone_field/assets/flags/cv.png": "9b1f31f9fc0795d728328dedd33eb1c0",
"assets/packages/intl_phone_field/assets/flags/hk.png": "4b5ec424348c98ec71a46ad3dce3931d",
"assets/packages/intl_phone_field/assets/flags/mt.png": "f3119401ae0c3a9d6e2dc23803928c06",
"assets/packages/intl_phone_field/assets/flags/ga.png": "b0e5b2fa1b7106c7652a955db24c11c4",
"assets/packages/intl_phone_field/assets/flags/ws.png": "f206322f3e22f175869869dbfadb6ce8",
"assets/packages/intl_phone_field/assets/flags/gq.png": "4286e56f388a37f64b21eb56550c06d9",
"assets/packages/intl_phone_field/assets/flags/cy.png": "7b36f4af86257a3f15f5a5a16f4a2fcd",
"assets/packages/intl_phone_field/assets/flags/co.png": "e3b1be16dcdae6cb72e9c238fdddce3c",
"assets/packages/intl_phone_field/assets/flags/lu.png": "6274fd1cae3c7a425d25e4ccb0941bb8",
"assets/packages/intl_phone_field/assets/flags/re.png": "134bee9f9d794dc5c0922d1b9bdbb710",
"assets/packages/intl_phone_field/assets/flags/km.png": "5554c8746c16d4f482986fb78ffd9b36",
"assets/packages/intl_phone_field/assets/flags/cw.png": "6c598eb0d331d6b238da57055ec00d33",
"assets/packages/intl_phone_field/assets/flags/pt.png": "eba93d33545c78cc67915d9be8323661",
"assets/packages/intl_phone_field/assets/flags/tn.png": "6612e9fec4bef022cbd45cbb7c02b2b6",
"assets/packages/intl_phone_field/assets/flags/to.png": "1cdd716b5b5502f85d6161dac6ee6c5b",
"assets/packages/intl_phone_field/assets/flags/ee.png": "e242645cae28bd5291116ea211f9a566",
"assets/packages/intl_phone_field/assets/flags/kw.png": "3ca448e219d0df506fb2efd5b91be092",
"assets/packages/intl_phone_field/assets/flags/mk.png": "835f2263974de523fa779d29c90595bf",
"assets/packages/intl_phone_field/assets/flags/cn.png": "040539c2cdb60ebd9dc8957cdc6a8ad0",
"assets/packages/intl_phone_field/assets/flags/me.png": "590284bc85810635ace30a173e615ca4",
"assets/packages/intl_phone_field/assets/flags/cu.png": "f41715bd51f63a9aebf543788543b4c4",
"assets/packages/intl_phone_field/assets/flags/br.png": "5093e0cd8fd3c094664cd17ea8a36fd1",
"assets/packages/intl_phone_field/assets/flags/pk.png": "7a6a621f7062589677b3296ca16c6718",
"assets/packages/intl_phone_field/assets/flags/na.png": "cdc00e9267a873609b0abea944939ff7",
"assets/packages/intl_phone_field/assets/flags/nu.png": "f4169998548e312584c67873e0d9352d",
"assets/packages/intl_phone_field/assets/flags/pm.png": "134bee9f9d794dc5c0922d1b9bdbb710",
"assets/packages/intl_phone_field/assets/flags/ph.png": "e4025d1395a8455f1ba038597a95228c",
"assets/packages/intl_phone_field/assets/flags/va.png": "c010bf145f695d5c8fb551bafc081f77",
"assets/packages/intl_phone_field/assets/flags/ni.png": "e398dc23e79d9ccd702546cc25f126bf",
"assets/packages/intl_phone_field/assets/flags/lb.png": "f80cde345f0d9bd0086531808ce5166a",
"assets/packages/intl_phone_field/assets/flags/ci.png": "7f5ca3779d5ff6ce0c803a6efa0d2da7",
"assets/packages/intl_phone_field/assets/flags/ki.png": "14db0fc29398730064503907bd696176",
"assets/packages/intl_phone_field/assets/flags/gi.png": "446aa44aaa063d240adab88243b460d3",
"assets/packages/intl_phone_field/assets/flags/td.png": "009303b6188ca0e30bd50074b16f0b16",
"assets/packages/intl_phone_field/assets/flags/gh.png": "b35464dca793fa33e51bf890b5f3d92b",
"assets/packages/intl_phone_field/assets/flags/sa.png": "7c95c1a877148e2aa21a213d720ff4fd",
"assets/packages/intl_phone_field/assets/flags/tw.png": "b1101fd5f871a9ffe7c9ad191a7d3304",
"assets/packages/intl_phone_field/assets/flags/li.png": "ecdf7b3fe932378b110851674335d9ab",
"assets/packages/intl_phone_field/assets/flags/bb.png": "a8473747387e4e7a8450c499529f1c93",
"assets/packages/intl_phone_field/assets/flags/th.png": "11ce0c9f8c738fd217ea52b9bc29014b",
"assets/packages/intl_phone_field/assets/flags/tf.png": "b2c044b86509e7960b5ba66b094ea285",
"assets/packages/intl_phone_field/assets/flags/ua.png": "b4b10d893611470661b079cb30473871",
"assets/packages/intl_phone_field/assets/flags/ie.png": "1d91912afc591dd120b47b56ea78cdbf",
"assets/packages/intl_phone_field/assets/flags/sj.png": "33bc70259c4908b7b9adeef9436f7a9f",
"assets/packages/intl_phone_field/assets/flags/yt.png": "134bee9f9d794dc5c0922d1b9bdbb710",
"assets/packages/intl_phone_field/assets/flags/aw.png": "a93ddf8e32d246dc47f6631f38e0ed92",
"assets/packages/intl_phone_field/assets/flags/bg.png": "1d24bc616e3389684ed2c9f18bcb0209",
"assets/packages/intl_phone_field/assets/flags/tt.png": "a8e1fc5c65dc8bc362a9453fadf9c4b3",
"assets/packages/intl_phone_field/assets/flags/tg.png": "7f91f02b26b74899ff882868bd611714",
"assets/packages/intl_phone_field/assets/flags/kg.png": "c4aa6d221d9a9d332155518d6b82dbc7",
"assets/packages/intl_phone_field/assets/flags/ba.png": "d415bad33b35de3f095177e8e86cbc82",
"assets/packages/intl_phone_field/assets/flags/sv.png": "217b691efbef7a0f48cdd53e91997f0e",
"assets/packages/intl_phone_field/assets/flags/ps.png": "52a25a48658ca9274830ffa124a8c1db",
"assets/packages/intl_phone_field/assets/flags/bv.png": "33bc70259c4908b7b9adeef9436f7a9f",
"assets/packages/intl_phone_field/assets/flags/vu.png": "3f201fdfb6d669a64c35c20a801016d1",
"assets/packages/intl_phone_field/assets/flags/be.png": "7e5e1831cdd91935b38415479a7110eb",
"assets/packages/intl_phone_field/assets/flags/ar.png": "3bd245f8c28f70c9ef9626dae27adc65",
"assets/packages/intl_phone_field/assets/flags/eh.png": "515a9cf2620c802e305b5412ac81aed2",
"assets/packages/intl_phone_field/assets/flags/vc.png": "da3ca14a978717467abbcdece05d3544",
"assets/packages/intl_phone_field/assets/flags/vn.png": "32ff65ccbf31a707a195be2a5141a89b",
"assets/packages/intl_phone_field/assets/flags/do.png": "ed35983a9263bb5713be37d9a52caddc",
"assets/packages/intl_phone_field/assets/flags/bt.png": "3cfe1440e952bc7266d71f7f1454fa23",
"assets/packages/intl_phone_field/assets/flags/pn.png": "0b0641b356af4c3e3489192ff4b0be77",
"assets/packages/intl_phone_field/assets/flags/fk.png": "da8b0fe48829aae2c8feb4839895de63",
"assets/packages/intl_phone_field/assets/flags/je.png": "288f8dca26098e83ff0455b08cceca1b",
"assets/packages/intl_phone_field/assets/flags/my.png": "f7f962e8a074387fd568c9d4024e0959",
"assets/packages/intl_phone_field/assets/flags/sh.png": "98773db151c150cabe845183241bfe6b",
"assets/packages/intl_phone_field/assets/flags/cg.png": "eca97338cc1cb5b5e91bec72af57b3d4",
"assets/packages/intl_phone_field/assets/flags/sz.png": "d1829842e45c2b2b29222c1b7e201591",
"assets/packages/intl_phone_field/assets/flags/ma.png": "057ea2e08587f1361b3547556adae0c2",
"assets/packages/intl_phone_field/assets/flags/vi.png": "3f317c56f31971b3179abd4e03847036",
"assets/packages/intl_phone_field/assets/flags/by.png": "beabf61e94fb3a4f7c7a7890488b213d",
"assets/packages/intl_phone_field/assets/flags/se.png": "25dd5434891ac1ca2ad1af59cda70f80",
"assets/packages/intl_phone_field/assets/flags/nr.png": "1316f3a8a419d8be1975912c712535ea",
"assets/packages/intl_phone_field/assets/flags/io.png": "83d45bbbff087d47b2b39f1c20598f52",
"assets/packages/intl_phone_field/assets/flags/gd.png": "7a4864ccfa2a0564041c2d1f8a13a8c9",
"assets/packages/intl_phone_field/assets/flags/ug.png": "9a0f358b1eb19863e21ae2063fab51c0",
"assets/packages/intl_phone_field/assets/flags/bj.png": "6fdc6449f73d23ad3f07060f92db4423",
"assets/packages/intl_phone_field/assets/flags/gb.png": "98773db151c150cabe845183241bfe6b",
"assets/packages/intl_phone_field/assets/flags/il.png": "1e06ad7783f24332405d36561024cc4c",
"assets/packages/intl_phone_field/assets/flags/fo.png": "2c7d9233582e83a86927e634897a2a90",
"assets/packages/intl_phone_field/assets/flags/ae.png": "792efc5eb6c31d780bd34bf4bad69f3f",
"assets/packages/intl_phone_field/assets/flags/eg.png": "311d780e8e3dd43f87e6070f6feb74c7",
"assets/packages/intl_phone_field/assets/flags/np.png": "6e099fb1e063930bdd00e8df5cef73d4",
"assets/packages/intl_phone_field/assets/flags/la.png": "e8cd9c3ee6e134adcbe3e986e1974e4a",
"assets/packages/intl_phone_field/assets/flags/zw.png": "078a3267ea8eabf88b2d43fe4aed5ce5",
"assets/packages/intl_phone_field/assets/flags/cz.png": "73ecd64c6144786c4d03729b1dd9b1f3",
"assets/packages/intl_phone_field/assets/flags/lc.png": "8c1a03a592aa0a99fcaf2b81508a87eb",
"assets/packages/intl_phone_field/assets/flags/ly.png": "8d65057351859065d64b4c118ff9e30e",
"assets/packages/intl_phone_field/assets/flags/ao.png": "5f0a372aa3aa7150a3dafea97acfc10d",
"assets/packages/intl_phone_field/assets/flags/pl.png": "f20e9ef473a9ed24176f5ad74dd0d50a",
"assets/packages/intl_phone_field/assets/flags/tk.png": "60428ff1cdbae680e5a0b8cde4677dd5",
"assets/packages/intl_phone_field/assets/flags/pg.png": "0f7e03465a93e0b4e3e1c9d3dd5814a4",
"assets/packages/intl_phone_field/assets/flags/ms.png": "9c955a926cf7d57fccb450a97192afa7",
"assets/packages/intl_phone_field/assets/flags/gw.png": "05606b9a6393971bd87718b809e054f9",
"assets/packages/intl_phone_field/assets/flags/de.png": "5d9561246523cf6183928756fd605e25",
"assets/packages/intl_phone_field/assets/flags/an.png": "4e4b90fbca1275d1839ca5b44fc51071",
"assets/packages/intl_phone_field/assets/flags/no.png": "33bc70259c4908b7b9adeef9436f7a9f",
"assets/packages/intl_phone_field/assets/flags/us.png": "83b065848d14d33c0d10a13e01862f34",
"assets/packages/intl_phone_field/assets/flags/ax.png": "ec2062c36f09ed8fb90ac8992d010024",
"assets/packages/intl_phone_field/assets/flags/ad.png": "384e9845debe9aca8f8586d9bedcb7e6",
"assets/packages/intl_phone_field/assets/flags/hn.png": "9ecf68aed83c4a9b3f1e6275d96bfb04",
"assets/packages/intl_phone_field/assets/flags/ye.png": "4cf73209d90e9f02ead1565c8fdf59e5",
"assets/packages/intl_phone_field/assets/flags/sg.png": "bc772e50b8c79f08f3c2189f5d8ce491",
"assets/packages/intl_phone_field/assets/flags/pw.png": "2e697cc6907a7b94c7f94f5d9b3bdccc",
"assets/packages/intl_phone_field/assets/flags/ec.png": "c1ae60d080be91f3be31e92e0a2d9555",
"assets/packages/intl_phone_field/assets/flags/fr.png": "134bee9f9d794dc5c0922d1b9bdbb710",
"assets/packages/intl_phone_field/assets/flags/kh.png": "d48d51e8769a26930da6edfc15de97fe",
"assets/packages/intl_phone_field/assets/flags/eu.png": "c58ece3931acb87faadc5b940d4f7755",
"assets/packages/intl_phone_field/assets/flags/tj.png": "c73b793f2acd262e71b9236e64c77636",
"assets/packages/intl_phone_field/assets/flags/tr.png": "27feab1a5ca390610d07e0c6bd4720d5",
"assets/packages/intl_phone_field/assets/flags/bd.png": "86a0e4bd8787dc8542137a407e0f987f",
"assets/packages/intl_phone_field/assets/flags/om.png": "cebd9ab4b9ab071b2142e21ae2129efc",
"assets/packages/intl_phone_field/assets/flags/am.png": "aaa39141fbc80205bebaa0200b55a13a",
"assets/packages/intl_phone_field/assets/flags/bo.png": "3ccf6fa7f9cbc27949b8418925e4e89c",
"assets/packages/intl_phone_field/assets/flags/zm.png": "81cec35b715f227328cad8f314acd797",
"assets/packages/intl_phone_field/assets/flags/ch.png": "a251702f7760b0aac141428ed60b7b66",
"assets/packages/intl_phone_field/assets/flags/gn.png": "b2287c03c88a72d968aa796a076ba056",
"assets/packages/intl_phone_field/assets/flags/sk.png": "2a1ee716d4b41c017ff1dbf3fd3ffc64",
"assets/packages/intl_phone_field/assets/flags/mq.png": "134bee9f9d794dc5c0922d1b9bdbb710",
"assets/packages/intl_phone_field/assets/flags/kz.png": "cb3b0095281c9d7e7fb5ce1716ef8ee5",
"assets/packages/intl_phone_field/assets/flags/gm.png": "7148d3715527544c2e7d8d6f4a445bb6",
"assets/packages/intl_phone_field/assets/flags/fi.png": "3ccd69a842e55183415b7ea2c04b15c8",
"assets/packages/intl_phone_field/assets/flags/al.png": "722cf9e5c7a1d9c9e4608fb44dbb427d",
"assets/packages/intl_phone_field/assets/flags/er.png": "8ca78e10878a2e97c1371b38c5d258a7",
"assets/packages/intl_phone_field/assets/flags/gg.png": "eed435d25bd755aa7f9cd7004b9ed49d",
"assets/packages/intl_phone_field/assets/flags/fj.png": "1c6a86752578eb132390febf12789cd6",
"assets/packages/intl_phone_field/assets/flags/gs.png": "419dd57836797a3f1bf6258ea6589f9a",
"assets/packages/intl_phone_field/assets/flags/ag.png": "41c11d5668c93ba6e452f811defdbb24",
"assets/packages/intl_phone_field/assets/flags/sx.png": "9c19254973d8acf81581ad95b408c7e6",
"assets/packages/intl_phone_field/assets/flags/jp.png": "25ac778acd990bedcfdc02a9b4570045",
"assets/packages/intl_phone_field/assets/flags/tl.png": "c80876dc80cda5ab6bb8ef078bc6b05d",
"assets/packages/intl_phone_field/assets/flags/gu.png": "2acb614b442e55864411b6e418df6eab",
"assets/packages/intl_phone_field/assets/flags/wf.png": "6f1644b8f907d197c0ff7ed2f366ad64",
"assets/packages/intl_phone_field/assets/flags/gl.png": "b79e24ee1889b7446ba3d65564b86810",
"assets/packages/intl_phone_field/assets/flags/st.png": "fef62c31713ff1063da2564df3f43eea",
"assets/packages/intl_phone_field/assets/flags/gp.png": "134bee9f9d794dc5c0922d1b9bdbb710",
"assets/packages/intl_phone_field/assets/flags/gb-eng.png": "0d9f2a6775fd52b79e1d78eb1dda10cf",
"assets/packages/intl_phone_field/assets/flags/sn.png": "68eaa89bbc83b3f356e1ba2096b09b3c",
"assets/packages/intl_phone_field/assets/flags/it.png": "5c8e910e6a33ec63dfcda6e8960dd19c",
"assets/packages/intl_phone_field/assets/flags/ir.png": "37f67c3141e9843196cb94815be7bd37",
"assets/packages/intl_phone_field/assets/flags/kn.png": "f318e2fd87e5fd2cabefe9ff252bba46",
"assets/packages/intl_phone_field/assets/flags/et.png": "57edff61c7fddf2761a19948acef1498",
"assets/packages/intl_phone_field/assets/flags/ky.png": "38e39eba673e82c48a1f25bd103a7e97",
"assets/packages/intl_phone_field/assets/flags/ss.png": "b0120cb000b31bb1a5c801c3592139bc",
"assets/packages/intl_phone_field/assets/flags/ro.png": "85af99741fe20664d9a7112cfd8d9722",
"assets/packages/intl_phone_field/assets/flags/mv.png": "d9245f74e34d5c054413ace4b86b4f16",
"assets/packages/intl_phone_field/assets/flags/es.png": "654965f9722f6706586476fb2f5d30dd",
"assets/packages/intl_phone_field/assets/flags/aq.png": "0c586e7b91aa192758fdd0f03adb84d8",
"assets/packages/intl_phone_field/assets/flags/bq.png": "3649c177693bfee9c2fcc63c191a51f1",
"assets/packages/intl_phone_field/assets/flags/bl.png": "dae94f5465d3390fdc5929e4f74d3f5f",
"assets/packages/intl_phone_field/assets/flags/nc.png": "cb36e0c945b79d56def11b23c6a9c7e9",
"assets/packages/intl_phone_field/assets/flags/pf.png": "1ae72c24380d087cbe2d0cd6c3b58821",
"assets/packages/intl_phone_field/assets/flags/in.png": "1dec13ba525529cffd4c7f8a35d51121",
"assets/packages/intl_phone_field/assets/flags/kp.png": "e1c8bb52f31fca22d3368d8f492d8f27",
"assets/packages/intl_phone_field/assets/flags/cr.png": "bfd8b41e63fc3cc829c72c4b2e170532",
"assets/packages/intl_phone_field/assets/flags/xk.png": "079259fbcb1f3c78dafa944464295c16",
"assets/packages/intl_phone_field/assets/flags/ge.png": "6fbd41f07921fa415347ebf6dff5b0f7",
"assets/packages/intl_phone_field/assets/flags/cc.png": "31a475216e12fef447382c97b42876ce",
"assets/packages/intl_phone_field/assets/flags/bi.png": "adda8121501f0543f1075244a1acc275",
"assets/packages/intl_phone_field/assets/flags/id.png": "80bb82d11d5bc144a21042e77972bca9",
"assets/packages/intl_phone_field/assets/flags/mx.png": "84b12a569b209e213daccfcbdd1fc799",
"assets/packages/intl_phone_field/assets/flags/mw.png": "ffc1f18eeedc1dfbb1080aa985ce7d05",
"assets/packages/intl_phone_field/assets/flags/um.png": "8fe7c4fed0a065fdfb9bd3125c6ecaa1",
"assets/packages/intl_phone_field/assets/flags/gy.png": "159a260bf0217128ea7475ba5b272b6a",
"assets/packages/intl_phone_field/assets/flags/sd.png": "65ce270762dfc87475ea99bd18f79025",
"assets/packages/intl_phone_field/assets/flags/lk.png": "5a3a063cfff4a92fb0ba6158e610e025",
"assets/packages/intl_phone_field/assets/flags/ru.png": "6974dcb42ad7eb3add1009ea0c6003e3",
"assets/packages/intl_phone_field/assets/flags/py.png": "154d4add03b4878caf00bd3249e14f40",
"assets/packages/intl_phone_field/assets/flags/tc.png": "d728d6763c17c520ad6bcf3c24282a29",
"assets/packages/window_manager/images/ic_chrome_unmaximize.png": "4a90c1909cb74e8f0d35794e2f61d8bf",
"assets/packages/window_manager/images/ic_chrome_minimize.png": "4282cd84cb36edf2efb950ad9269ca62",
"assets/packages/window_manager/images/ic_chrome_close.png": "75f4b8ab3608a05461a31fc18d6b47c2",
"assets/packages/window_manager/images/ic_chrome_maximize.png": "af7499d7657c8b69d23b85156b60298c",
"assets/assets/google_fonts/Roboto-Regular.ttf": "8a36205bd9b83e03af0591a004bc97f4",
"assets/assets/images/payment_types/maestro.png": "e533b92bfb50339fdbfa79e3dfe81f08",
"assets/assets/images/payment_types/jcb.png": "07e0942d16c5592118b72e74f2f7198c",
"assets/assets/images/payment_types/carteblanche.png": "d936e11fa3884b8c9f1bd5c914be8629",
"assets/assets/images/payment_types/mastercard.png": "6f6cdc29ee2e22e06b1ac029cb52ef71",
"assets/assets/images/payment_types/solo.png": "2030c3ccaccf5d5e87916a62f5b084d6",
"assets/assets/images/payment_types/laser.png": "b4e6e93dd35517ac429301119ff05868",
"assets/assets/images/payment_types/dinerscard.png": "06d85186ba858c18ab7c9caa42c92024",
"assets/assets/images/payment_types/discover.png": "6c0a386a00307f87db7bea366cca35f5",
"assets/assets/images/payment_types/unionpay.png": "7002f52004e0ab8cc0b7450b0208ccb2",
"assets/assets/images/payment_types/paypal.png": "8e06c094c1871376dfea1da8088c29d1",
"assets/assets/images/payment_types/switch.png": "4fa11c45327f5fdc20205821b2cfd9cc",
"assets/assets/images/payment_types/other.png": "d936e11fa3884b8c9f1bd5c914be8629",
"assets/assets/images/payment_types/ach.png": "7433f0aff779dc98a649b7a2daf777cf",
"assets/assets/images/payment_types/visa.png": "3ddc4a4d25c946e8ad7e6998f30fd4e3",
"assets/assets/images/payment_types/amex.png": "c49a4247984b3732a4af50a3390aa978",
"assets/assets/images/logo_dark.png": "a233ed1d4d0f7414bf97a9a10f11fb0a",
"assets/assets/images/logo_light.png": "e5f46d5a78e226e7a9553d4ca6f69219",
"assets/assets/images/google_logo.png": "0f118259ce403274f407f5e982e681c3",
"assets/assets/images/icon.png": "090f69e23311a4b6d851b3880ae52541",
"assets/AssetManifest.bin.json": "611449d46e56c96b3baef404bfc56246",
"assets/shaders/ink_sparkle.frag": "ecc85a2e95f5e9f53123dcaf8cb9b6ce",
"assets/NOTICES": "412b336cf9e33e70058d612857effae1",
"assets/fonts/MaterialIcons-Regular.otf": "a57618538ab8b4c4081d4491870ac333",
"assets/AssetManifest.json": "759f9ef9973f7e26c2a51450b55bb9fa",
"main.dart.js": "bd68d64a60de3a8c0afbd24c36cfcdac",
"favicon.png": "dca91c54388f52eded692718d5a98b8b", "favicon.png": "dca91c54388f52eded692718d5a98b8b",
"version.json": "4dada3a779a2983f2adddf16b9f4015e", "version.json": "4dada3a779a2983f2adddf16b9f4015e",
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed", "favicon.ico": "51636d3a390451561744c42188ccd628",
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35"}; "/": "cde2c9fecf78946ae6d89dadc614e946",
"main.dart.js": "468dd28262bf65628c11ca1edbd0ee09",
"assets/AssetManifest.json": "759f9ef9973f7e26c2a51450b55bb9fa",
"assets/packages/intl_phone_field/assets/flags/mn.png": "16086e8d89c9067d29fd0f2ea7021a45",
"assets/packages/intl_phone_field/assets/flags/vi.png": "3f317c56f31971b3179abd4e03847036",
"assets/packages/intl_phone_field/assets/flags/cv.png": "9b1f31f9fc0795d728328dedd33eb1c0",
"assets/packages/intl_phone_field/assets/flags/tv.png": "c57025ed7ae482210f29b9da86b0d211",
"assets/packages/intl_phone_field/assets/flags/bo.png": "3ccf6fa7f9cbc27949b8418925e4e89c",
"assets/packages/intl_phone_field/assets/flags/ch.png": "a251702f7760b0aac141428ed60b7b66",
"assets/packages/intl_phone_field/assets/flags/sl.png": "61b9d992c8a6a83abc4d432069617811",
"assets/packages/intl_phone_field/assets/flags/ne.png": "a20724c177e86d6a27143aa9c9664a6f",
"assets/packages/intl_phone_field/assets/flags/ck.png": "39f343868a8dc8ca95d27b27a5caf480",
"assets/packages/intl_phone_field/assets/flags/ve.png": "893391d65cbd10ca787a73578c77d3a7",
"assets/packages/intl_phone_field/assets/flags/lv.png": "53105fea0cc9cc554e0ceaabc53a2d5d",
"assets/packages/intl_phone_field/assets/flags/tz.png": "56ec99c7e0f68b88a2210620d873683a",
"assets/packages/intl_phone_field/assets/flags/ug.png": "9a0f358b1eb19863e21ae2063fab51c0",
"assets/packages/intl_phone_field/assets/flags/ma.png": "057ea2e08587f1361b3547556adae0c2",
"assets/packages/intl_phone_field/assets/flags/eh.png": "515a9cf2620c802e305b5412ac81aed2",
"assets/packages/intl_phone_field/assets/flags/as.png": "d9c1da515c6f945c2e2554592a9dfaae",
"assets/packages/intl_phone_field/assets/flags/al.png": "722cf9e5c7a1d9c9e4608fb44dbb427d",
"assets/packages/intl_phone_field/assets/flags/pe.png": "4d9249aab70a26fadabb14380b3b55d2",
"assets/packages/intl_phone_field/assets/flags/lt.png": "7df2cd6566725685f7feb2051f916a3e",
"assets/packages/intl_phone_field/assets/flags/fo.png": "2c7d9233582e83a86927e634897a2a90",
"assets/packages/intl_phone_field/assets/flags/cd.png": "5b5f832ed6cd9f9240cb31229d8763dc",
"assets/packages/intl_phone_field/assets/flags/ls.png": "2bca756f9313957347404557acb532b0",
"assets/packages/intl_phone_field/assets/flags/mw.png": "ffc1f18eeedc1dfbb1080aa985ce7d05",
"assets/packages/intl_phone_field/assets/flags/kh.png": "d48d51e8769a26930da6edfc15de97fe",
"assets/packages/intl_phone_field/assets/flags/mq.png": "134bee9f9d794dc5c0922d1b9bdbb710",
"assets/packages/intl_phone_field/assets/flags/ng.png": "aedbe364bd1543832e88e64b5817e877",
"assets/packages/intl_phone_field/assets/flags/tg.png": "7f91f02b26b74899ff882868bd611714",
"assets/packages/intl_phone_field/assets/flags/gr.png": "ec11281d7decbf07b81a23a72a609b59",
"assets/packages/intl_phone_field/assets/flags/bn.png": "ed650de06fff61ff27ec92a872197948",
"assets/packages/intl_phone_field/assets/flags/sc.png": "e969fd5afb1eb5902675b6bcf49a8c2e",
"assets/packages/intl_phone_field/assets/flags/kg.png": "c4aa6d221d9a9d332155518d6b82dbc7",
"assets/packages/intl_phone_field/assets/flags/no.png": "33bc70259c4908b7b9adeef9436f7a9f",
"assets/packages/intl_phone_field/assets/flags/ws.png": "f206322f3e22f175869869dbfadb6ce8",
"assets/packages/intl_phone_field/assets/flags/er.png": "8ca78e10878a2e97c1371b38c5d258a7",
"assets/packages/intl_phone_field/assets/flags/cn.png": "040539c2cdb60ebd9dc8957cdc6a8ad0",
"assets/packages/intl_phone_field/assets/flags/zw.png": "078a3267ea8eabf88b2d43fe4aed5ce5",
"assets/packages/intl_phone_field/assets/flags/sm.png": "a8d6801cb7c5360e18f0a2ed146b396d",
"assets/packages/intl_phone_field/assets/flags/gu.png": "2acb614b442e55864411b6e418df6eab",
"assets/packages/intl_phone_field/assets/flags/am.png": "aaa39141fbc80205bebaa0200b55a13a",
"assets/packages/intl_phone_field/assets/flags/cr.png": "bfd8b41e63fc3cc829c72c4b2e170532",
"assets/packages/intl_phone_field/assets/flags/af.png": "ba710b50a060b5351381b55366396c30",
"assets/packages/intl_phone_field/assets/flags/sg.png": "bc772e50b8c79f08f3c2189f5d8ce491",
"assets/packages/intl_phone_field/assets/flags/kr.png": "a3b7da3b76b20a70e9cd63cc2315b51b",
"assets/packages/intl_phone_field/assets/flags/gt.png": "706a0c3b5e0b589c843e2539e813839e",
"assets/packages/intl_phone_field/assets/flags/uy.png": "da4247b21fcbd9e30dc2b3f7c5dccb64",
"assets/packages/intl_phone_field/assets/flags/sn.png": "68eaa89bbc83b3f356e1ba2096b09b3c",
"assets/packages/intl_phone_field/assets/flags/va.png": "c010bf145f695d5c8fb551bafc081f77",
"assets/packages/intl_phone_field/assets/flags/my.png": "f7f962e8a074387fd568c9d4024e0959",
"assets/packages/intl_phone_field/assets/flags/cz.png": "73ecd64c6144786c4d03729b1dd9b1f3",
"assets/packages/intl_phone_field/assets/flags/mv.png": "d9245f74e34d5c054413ace4b86b4f16",
"assets/packages/intl_phone_field/assets/flags/bz.png": "fd2d7d27a5ddabe4eb9a10b1d3a433e4",
"assets/packages/intl_phone_field/assets/flags/lk.png": "5a3a063cfff4a92fb0ba6158e610e025",
"assets/packages/intl_phone_field/assets/flags/ps.png": "52a25a48658ca9274830ffa124a8c1db",
"assets/packages/intl_phone_field/assets/flags/cx.png": "8efa3231c8a3900a78f2b51d829f8c52",
"assets/packages/intl_phone_field/assets/flags/gb.png": "98773db151c150cabe845183241bfe6b",
"assets/packages/intl_phone_field/assets/flags/wf.png": "6f1644b8f907d197c0ff7ed2f366ad64",
"assets/packages/intl_phone_field/assets/flags/cf.png": "263583ffdf7a888ce4fba8487d1da0b2",
"assets/packages/intl_phone_field/assets/flags/gs.png": "419dd57836797a3f1bf6258ea6589f9a",
"assets/packages/intl_phone_field/assets/flags/au.png": "72be14316f0af3903cdca7a726c0c589",
"assets/packages/intl_phone_field/assets/flags/re.png": "134bee9f9d794dc5c0922d1b9bdbb710",
"assets/packages/intl_phone_field/assets/flags/ly.png": "8d65057351859065d64b4c118ff9e30e",
"assets/packages/intl_phone_field/assets/flags/lb.png": "f80cde345f0d9bd0086531808ce5166a",
"assets/packages/intl_phone_field/assets/flags/ca.png": "76f2fac1d3b2cc52ba6695c2e2941632",
"assets/packages/intl_phone_field/assets/flags/ht.png": "630f7f8567d87409a32955107ad11a86",
"assets/packages/intl_phone_field/assets/flags/dz.png": "132ceca353a95c8214676b2e94ecd40f",
"assets/packages/intl_phone_field/assets/flags/dm.png": "8886b222ed9ccd00f67e8bcf86dadcc2",
"assets/packages/intl_phone_field/assets/flags/kz.png": "cb3b0095281c9d7e7fb5ce1716ef8ee5",
"assets/packages/intl_phone_field/assets/flags/gb-nir.png": "98773db151c150cabe845183241bfe6b",
"assets/packages/intl_phone_field/assets/flags/bm.png": "b366ba84cbc8286c830f392bb9086be5",
"assets/packages/intl_phone_field/assets/flags/si.png": "24237e53b34752554915e71e346bb405",
"assets/packages/intl_phone_field/assets/flags/mg.png": "0ef6271ad284ebc0069ff0aeb5a3ad1e",
"assets/packages/intl_phone_field/assets/flags/mx.png": "84b12a569b209e213daccfcbdd1fc799",
"assets/packages/intl_phone_field/assets/flags/jp.png": "25ac778acd990bedcfdc02a9b4570045",
"assets/packages/intl_phone_field/assets/flags/sv.png": "217b691efbef7a0f48cdd53e91997f0e",
"assets/packages/intl_phone_field/assets/flags/ee.png": "e242645cae28bd5291116ea211f9a566",
"assets/packages/intl_phone_field/assets/flags/ga.png": "b0e5b2fa1b7106c7652a955db24c11c4",
"assets/packages/intl_phone_field/assets/flags/fr.png": "134bee9f9d794dc5c0922d1b9bdbb710",
"assets/packages/intl_phone_field/assets/flags/to.png": "1cdd716b5b5502f85d6161dac6ee6c5b",
"assets/packages/intl_phone_field/assets/flags/nr.png": "1316f3a8a419d8be1975912c712535ea",
"assets/packages/intl_phone_field/assets/flags/jo.png": "c01cb41f74f9db0cf07ba20f0af83011",
"assets/packages/intl_phone_field/assets/flags/pg.png": "0f7e03465a93e0b4e3e1c9d3dd5814a4",
"assets/packages/intl_phone_field/assets/flags/tn.png": "6612e9fec4bef022cbd45cbb7c02b2b6",
"assets/packages/intl_phone_field/assets/flags/bh.png": "a1acd86ef0e19ea5f0297bbe1de6cfd4",
"assets/packages/intl_phone_field/assets/flags/zm.png": "81cec35b715f227328cad8f314acd797",
"assets/packages/intl_phone_field/assets/flags/xk.png": "079259fbcb1f3c78dafa944464295c16",
"assets/packages/intl_phone_field/assets/flags/ag.png": "41c11d5668c93ba6e452f811defdbb24",
"assets/packages/intl_phone_field/assets/flags/sr.png": "9f912879f2829a625436ccd15e643e39",
"assets/packages/intl_phone_field/assets/flags/gm.png": "7148d3715527544c2e7d8d6f4a445bb6",
"assets/packages/intl_phone_field/assets/flags/lu.png": "6274fd1cae3c7a425d25e4ccb0941bb8",
"assets/packages/intl_phone_field/assets/flags/na.png": "cdc00e9267a873609b0abea944939ff7",
"assets/packages/intl_phone_field/assets/flags/ge.png": "6fbd41f07921fa415347ebf6dff5b0f7",
"assets/packages/intl_phone_field/assets/flags/fk.png": "da8b0fe48829aae2c8feb4839895de63",
"assets/packages/intl_phone_field/assets/flags/cg.png": "eca97338cc1cb5b5e91bec72af57b3d4",
"assets/packages/intl_phone_field/assets/flags/gi.png": "446aa44aaa063d240adab88243b460d3",
"assets/packages/intl_phone_field/assets/flags/is.png": "907840430252c431518005b562707831",
"assets/packages/intl_phone_field/assets/flags/sa.png": "7c95c1a877148e2aa21a213d720ff4fd",
"assets/packages/intl_phone_field/assets/flags/im.png": "7c9ccb825f0fca557d795c4330cf4f50",
"assets/packages/intl_phone_field/assets/flags/eu.png": "c58ece3931acb87faadc5b940d4f7755",
"assets/packages/intl_phone_field/assets/flags/ro.png": "85af99741fe20664d9a7112cfd8d9722",
"assets/packages/intl_phone_field/assets/flags/it.png": "5c8e910e6a33ec63dfcda6e8960dd19c",
"assets/packages/intl_phone_field/assets/flags/tf.png": "b2c044b86509e7960b5ba66b094ea285",
"assets/packages/intl_phone_field/assets/flags/ai.png": "ce5e91ed1725f0499b9231b69a7fd448",
"assets/packages/intl_phone_field/assets/flags/np.png": "6e099fb1e063930bdd00e8df5cef73d4",
"assets/packages/intl_phone_field/assets/flags/tr.png": "27feab1a5ca390610d07e0c6bd4720d5",
"assets/packages/intl_phone_field/assets/flags/om.png": "cebd9ab4b9ab071b2142e21ae2129efc",
"assets/packages/intl_phone_field/assets/flags/ad.png": "384e9845debe9aca8f8586d9bedcb7e6",
"assets/packages/intl_phone_field/assets/flags/nz.png": "65c811e96eb6c9da65538f899c110895",
"assets/packages/intl_phone_field/assets/flags/et.png": "57edff61c7fddf2761a19948acef1498",
"assets/packages/intl_phone_field/assets/flags/py.png": "154d4add03b4878caf00bd3249e14f40",
"assets/packages/intl_phone_field/assets/flags/ss.png": "b0120cb000b31bb1a5c801c3592139bc",
"assets/packages/intl_phone_field/assets/flags/mr.png": "f2a62602d43a1ee14625af165b96ce2f",
"assets/packages/intl_phone_field/assets/flags/bq.png": "3649c177693bfee9c2fcc63c191a51f1",
"assets/packages/intl_phone_field/assets/flags/pl.png": "f20e9ef473a9ed24176f5ad74dd0d50a",
"assets/packages/intl_phone_field/assets/flags/gb-eng.png": "0d9f2a6775fd52b79e1d78eb1dda10cf",
"assets/packages/intl_phone_field/assets/flags/vn.png": "32ff65ccbf31a707a195be2a5141a89b",
"assets/packages/intl_phone_field/assets/flags/aw.png": "a93ddf8e32d246dc47f6631f38e0ed92",
"assets/packages/intl_phone_field/assets/flags/mh.png": "18dda388ef5c1cf37cae5e7d5fef39bc",
"assets/packages/intl_phone_field/assets/flags/mm.png": "32e5293d6029d8294c7dfc3c3835c222",
"assets/packages/intl_phone_field/assets/flags/es.png": "654965f9722f6706586476fb2f5d30dd",
"assets/packages/intl_phone_field/assets/flags/nu.png": "f4169998548e312584c67873e0d9352d",
"assets/packages/intl_phone_field/assets/flags/sb.png": "296ecedbd8d1c2a6422c3ba8e5cd54bd",
"assets/packages/intl_phone_field/assets/flags/gb-sct.png": "75106a5e49e3e16da76cb33bdac102ab",
"assets/packages/intl_phone_field/assets/flags/ci.png": "7f5ca3779d5ff6ce0c803a6efa0d2da7",
"assets/packages/intl_phone_field/assets/flags/th.png": "11ce0c9f8c738fd217ea52b9bc29014b",
"assets/packages/intl_phone_field/assets/flags/pm.png": "134bee9f9d794dc5c0922d1b9bdbb710",
"assets/packages/intl_phone_field/assets/flags/mk.png": "835f2263974de523fa779d29c90595bf",
"assets/packages/intl_phone_field/assets/flags/gd.png": "7a4864ccfa2a0564041c2d1f8a13a8c9",
"assets/packages/intl_phone_field/assets/flags/bf.png": "63f1c67fca7ce8b52b3418a90af6ad37",
"assets/packages/intl_phone_field/assets/flags/bd.png": "86a0e4bd8787dc8542137a407e0f987f",
"assets/packages/intl_phone_field/assets/flags/bg.png": "1d24bc616e3389684ed2c9f18bcb0209",
"assets/packages/intl_phone_field/assets/flags/bi.png": "adda8121501f0543f1075244a1acc275",
"assets/packages/intl_phone_field/assets/flags/ms.png": "9c955a926cf7d57fccb450a97192afa7",
"assets/packages/intl_phone_field/assets/flags/bj.png": "6fdc6449f73d23ad3f07060f92db4423",
"assets/packages/intl_phone_field/assets/flags/ml.png": "0c50dfd539e87bb4313da0d4556e2d13",
"assets/packages/intl_phone_field/assets/flags/sx.png": "9c19254973d8acf81581ad95b408c7e6",
"assets/packages/intl_phone_field/assets/flags/sk.png": "2a1ee716d4b41c017ff1dbf3fd3ffc64",
"assets/packages/intl_phone_field/assets/flags/mo.png": "849848a26bbfc87024017418ad7a6233",
"assets/packages/intl_phone_field/assets/flags/pk.png": "7a6a621f7062589677b3296ca16c6718",
"assets/packages/intl_phone_field/assets/flags/se.png": "25dd5434891ac1ca2ad1af59cda70f80",
"assets/packages/intl_phone_field/assets/flags/hm.png": "72be14316f0af3903cdca7a726c0c589",
"assets/packages/intl_phone_field/assets/flags/ir.png": "37f67c3141e9843196cb94815be7bd37",
"assets/packages/intl_phone_field/assets/flags/je.png": "288f8dca26098e83ff0455b08cceca1b",
"assets/packages/intl_phone_field/assets/flags/ye.png": "4cf73209d90e9f02ead1565c8fdf59e5",
"assets/packages/intl_phone_field/assets/flags/sj.png": "33bc70259c4908b7b9adeef9436f7a9f",
"assets/packages/intl_phone_field/assets/flags/la.png": "e8cd9c3ee6e134adcbe3e986e1974e4a",
"assets/packages/intl_phone_field/assets/flags/gh.png": "b35464dca793fa33e51bf890b5f3d92b",
"assets/packages/intl_phone_field/assets/flags/kp.png": "e1c8bb52f31fca22d3368d8f492d8f27",
"assets/packages/intl_phone_field/assets/flags/sd.png": "65ce270762dfc87475ea99bd18f79025",
"assets/packages/intl_phone_field/assets/flags/dj.png": "078bd37d41f746c3cb2d84c1e9611c55",
"assets/packages/intl_phone_field/assets/flags/pt.png": "eba93d33545c78cc67915d9be8323661",
"assets/packages/intl_phone_field/assets/flags/jm.png": "074400103847c56c37425a73f9d23665",
"assets/packages/intl_phone_field/assets/flags/yt.png": "134bee9f9d794dc5c0922d1b9bdbb710",
"assets/packages/intl_phone_field/assets/flags/td.png": "009303b6188ca0e30bd50074b16f0b16",
"assets/packages/intl_phone_field/assets/flags/sz.png": "d1829842e45c2b2b29222c1b7e201591",
"assets/packages/intl_phone_field/assets/flags/tj.png": "c73b793f2acd262e71b9236e64c77636",
"assets/packages/intl_phone_field/assets/flags/kw.png": "3ca448e219d0df506fb2efd5b91be092",
"assets/packages/intl_phone_field/assets/flags/gw.png": "05606b9a6393971bd87718b809e054f9",
"assets/packages/intl_phone_field/assets/flags/eg.png": "311d780e8e3dd43f87e6070f6feb74c7",
"assets/packages/intl_phone_field/assets/flags/nc.png": "cb36e0c945b79d56def11b23c6a9c7e9",
"assets/packages/intl_phone_field/assets/flags/at.png": "570c070177a5ea0fe03e20107ebf5283",
"assets/packages/intl_phone_field/assets/flags/vu.png": "3f201fdfb6d669a64c35c20a801016d1",
"assets/packages/intl_phone_field/assets/flags/ph.png": "e4025d1395a8455f1ba038597a95228c",
"assets/packages/intl_phone_field/assets/flags/lr.png": "b92c75e18dd97349c75d6a43bd17ee94",
"assets/packages/intl_phone_field/assets/flags/cc.png": "31a475216e12fef447382c97b42876ce",
"assets/packages/intl_phone_field/assets/flags/bb.png": "a8473747387e4e7a8450c499529f1c93",
"assets/packages/intl_phone_field/assets/flags/by.png": "beabf61e94fb3a4f7c7a7890488b213d",
"assets/packages/intl_phone_field/assets/flags/mz.png": "1ab1ac750fbbb453d33e9f25850ac2a0",
"assets/packages/intl_phone_field/assets/flags/mt.png": "f3119401ae0c3a9d6e2dc23803928c06",
"assets/packages/intl_phone_field/assets/flags/mu.png": "c5228d1e94501d846b5bf203f038ae49",
"assets/packages/intl_phone_field/assets/flags/lc.png": "8c1a03a592aa0a99fcaf2b81508a87eb",
"assets/packages/intl_phone_field/assets/flags/us.png": "83b065848d14d33c0d10a13e01862f34",
"assets/packages/intl_phone_field/assets/flags/hn.png": "9ecf68aed83c4a9b3f1e6275d96bfb04",
"assets/packages/intl_phone_field/assets/flags/rs.png": "9dff535d2d08c504be63062f39eff0b7",
"assets/packages/intl_phone_field/assets/flags/hr.png": "69711b2ea009a3e7c40045b538768d4e",
"assets/packages/intl_phone_field/assets/flags/hk.png": "4b5ec424348c98ec71a46ad3dce3931d",
"assets/packages/intl_phone_field/assets/flags/pa.png": "78e3e4fd56f0064837098fe3f22fb41b",
"assets/packages/intl_phone_field/assets/flags/ki.png": "14db0fc29398730064503907bd696176",
"assets/packages/intl_phone_field/assets/flags/fm.png": "d571b8bc4b80980a81a5edbde788b6d2",
"assets/packages/intl_phone_field/assets/flags/ke.png": "cf5aae3699d3cacb39db9803edae172b",
"assets/packages/intl_phone_field/assets/flags/tm.png": "0980fb40ec450f70896f2c588510f933",
"assets/packages/intl_phone_field/assets/flags/ba.png": "d415bad33b35de3f095177e8e86cbc82",
"assets/packages/intl_phone_field/assets/flags/nf.png": "1c2069b299ce3660a2a95ec574dfde25",
"assets/packages/intl_phone_field/assets/flags/tk.png": "60428ff1cdbae680e5a0b8cde4677dd5",
"assets/packages/intl_phone_field/assets/flags/ao.png": "5f0a372aa3aa7150a3dafea97acfc10d",
"assets/packages/intl_phone_field/assets/flags/fi.png": "3ccd69a842e55183415b7ea2c04b15c8",
"assets/packages/intl_phone_field/assets/flags/in.png": "1dec13ba525529cffd4c7f8a35d51121",
"assets/packages/intl_phone_field/assets/flags/br.png": "5093e0cd8fd3c094664cd17ea8a36fd1",
"assets/packages/intl_phone_field/assets/flags/pw.png": "2e697cc6907a7b94c7f94f5d9b3bdccc",
"assets/packages/intl_phone_field/assets/flags/ae.png": "792efc5eb6c31d780bd34bf4bad69f3f",
"assets/packages/intl_phone_field/assets/flags/me.png": "590284bc85810635ace30a173e615ca4",
"assets/packages/intl_phone_field/assets/flags/nl.png": "3649c177693bfee9c2fcc63c191a51f1",
"assets/packages/intl_phone_field/assets/flags/cw.png": "6c598eb0d331d6b238da57055ec00d33",
"assets/packages/intl_phone_field/assets/flags/bs.png": "2b9540c4fa514f71911a48de0bd77e71",
"assets/packages/intl_phone_field/assets/flags/km.png": "5554c8746c16d4f482986fb78ffd9b36",
"assets/packages/intl_phone_field/assets/flags/sh.png": "98773db151c150cabe845183241bfe6b",
"assets/packages/intl_phone_field/assets/flags/tw.png": "b1101fd5f871a9ffe7c9ad191a7d3304",
"assets/packages/intl_phone_field/assets/flags/iq.png": "bc3e6f68c5188dbf99b473e2bea066f2",
"assets/packages/intl_phone_field/assets/flags/tt.png": "a8e1fc5c65dc8bc362a9453fadf9c4b3",
"assets/packages/intl_phone_field/assets/flags/hu.png": "281582a753e643b46bdd894047db08bb",
"assets/packages/intl_phone_field/assets/flags/za.png": "b28280c6c3eb4624c18b5455d4a1b1ff",
"assets/packages/intl_phone_field/assets/flags/pr.png": "b97b2f4432c430bc340d893f36527e31",
"assets/packages/intl_phone_field/assets/flags/kn.png": "f318e2fd87e5fd2cabefe9ff252bba46",
"assets/packages/intl_phone_field/assets/flags/be.png": "7e5e1831cdd91935b38415479a7110eb",
"assets/packages/intl_phone_field/assets/flags/gl.png": "b79e24ee1889b7446ba3d65564b86810",
"assets/packages/intl_phone_field/assets/flags/gp.png": "134bee9f9d794dc5c0922d1b9bdbb710",
"assets/packages/intl_phone_field/assets/flags/sy.png": "24186a0f4ce804a16c91592db5a16a3a",
"assets/packages/intl_phone_field/assets/flags/qa.png": "eb9b3388e554cf85aea1e739247548df",
"assets/packages/intl_phone_field/assets/flags/st.png": "fef62c31713ff1063da2564df3f43eea",
"assets/packages/intl_phone_field/assets/flags/cy.png": "7b36f4af86257a3f15f5a5a16f4a2fcd",
"assets/packages/intl_phone_field/assets/flags/ar.png": "3bd245f8c28f70c9ef9626dae27adc65",
"assets/packages/intl_phone_field/assets/flags/bt.png": "3cfe1440e952bc7266d71f7f1454fa23",
"assets/packages/intl_phone_field/assets/flags/li.png": "ecdf7b3fe932378b110851674335d9ab",
"assets/packages/intl_phone_field/assets/flags/vc.png": "da3ca14a978717467abbcdece05d3544",
"assets/packages/intl_phone_field/assets/flags/cm.png": "42d52fa71e8b4dbb182ff431749e8d0d",
"assets/packages/intl_phone_field/assets/flags/aq.png": "0c586e7b91aa192758fdd0f03adb84d8",
"assets/packages/intl_phone_field/assets/flags/cl.png": "6735e0e2d88c119e9ed1533be5249ef1",
"assets/packages/intl_phone_field/assets/flags/cu.png": "f41715bd51f63a9aebf543788543b4c4",
"assets/packages/intl_phone_field/assets/flags/gq.png": "4286e56f388a37f64b21eb56550c06d9",
"assets/packages/intl_phone_field/assets/flags/ru.png": "6974dcb42ad7eb3add1009ea0c6003e3",
"assets/packages/intl_phone_field/assets/flags/bl.png": "dae94f5465d3390fdc5929e4f74d3f5f",
"assets/packages/intl_phone_field/assets/flags/gg.png": "eed435d25bd755aa7f9cd7004b9ed49d",
"assets/packages/intl_phone_field/assets/flags/mc.png": "90c2ad7f144d73d4650cbea9dd621275",
"assets/packages/intl_phone_field/assets/flags/io.png": "83d45bbbff087d47b2b39f1c20598f52",
"assets/packages/intl_phone_field/assets/flags/ax.png": "ec2062c36f09ed8fb90ac8992d010024",
"assets/packages/intl_phone_field/assets/flags/co.png": "e3b1be16dcdae6cb72e9c238fdddce3c",
"assets/packages/intl_phone_field/assets/flags/de.png": "5d9561246523cf6183928756fd605e25",
"assets/packages/intl_phone_field/assets/flags/do.png": "ed35983a9263bb5713be37d9a52caddc",
"assets/packages/intl_phone_field/assets/flags/ie.png": "1d91912afc591dd120b47b56ea78cdbf",
"assets/packages/intl_phone_field/assets/flags/dk.png": "abcd01bdbcc02b4a29cbac237f29cd1d",
"assets/packages/intl_phone_field/assets/flags/pn.png": "0b0641b356af4c3e3489192ff4b0be77",
"assets/packages/intl_phone_field/assets/flags/gy.png": "159a260bf0217128ea7475ba5b272b6a",
"assets/packages/intl_phone_field/assets/flags/so.png": "1ce20d052f9d057250be96f42647513b",
"assets/packages/intl_phone_field/assets/flags/md.png": "8911d3d821b95b00abbba8771e997eb3",
"assets/packages/intl_phone_field/assets/flags/fj.png": "1c6a86752578eb132390febf12789cd6",
"assets/packages/intl_phone_field/assets/flags/vg.png": "fc095e11f5b58604d6f4d3c2b43d167f",
"assets/packages/intl_phone_field/assets/flags/pf.png": "1ae72c24380d087cbe2d0cd6c3b58821",
"assets/packages/intl_phone_field/assets/flags/il.png": "1e06ad7783f24332405d36561024cc4c",
"assets/packages/intl_phone_field/assets/flags/ua.png": "b4b10d893611470661b079cb30473871",
"assets/packages/intl_phone_field/assets/flags/ni.png": "e398dc23e79d9ccd702546cc25f126bf",
"assets/packages/intl_phone_field/assets/flags/tl.png": "c80876dc80cda5ab6bb8ef078bc6b05d",
"assets/packages/intl_phone_field/assets/flags/rw.png": "d1aae0647a5b1ab977ae43ab894ce2c3",
"assets/packages/intl_phone_field/assets/flags/tc.png": "d728d6763c17c520ad6bcf3c24282a29",
"assets/packages/intl_phone_field/assets/flags/mf.png": "134bee9f9d794dc5c0922d1b9bdbb710",
"assets/packages/intl_phone_field/assets/flags/bv.png": "33bc70259c4908b7b9adeef9436f7a9f",
"assets/packages/intl_phone_field/assets/flags/bw.png": "fac8b90d7404728c08686dc39bab4fb3",
"assets/packages/intl_phone_field/assets/flags/um.png": "8fe7c4fed0a065fdfb9bd3125c6ecaa1",
"assets/packages/intl_phone_field/assets/flags/gn.png": "b2287c03c88a72d968aa796a076ba056",
"assets/packages/intl_phone_field/assets/flags/gf.png": "134bee9f9d794dc5c0922d1b9bdbb710",
"assets/packages/intl_phone_field/assets/flags/id.png": "80bb82d11d5bc144a21042e77972bca9",
"assets/packages/intl_phone_field/assets/flags/az.png": "6ffa766f6883d2d3d350cdc22a062ca3",
"assets/packages/intl_phone_field/assets/flags/ec.png": "c1ae60d080be91f3be31e92e0a2d9555",
"assets/packages/intl_phone_field/assets/flags/an.png": "4e4b90fbca1275d1839ca5b44fc51071",
"assets/packages/intl_phone_field/assets/flags/mp.png": "87351c30a529071ee9a4bb67765fea4f",
"assets/packages/intl_phone_field/assets/flags/gb-wls.png": "d7d7c77c72cd425d993bdc50720f4d04",
"assets/packages/intl_phone_field/assets/flags/uz.png": "3adad3bac322220cac8abc1c7cbaacac",
"assets/packages/intl_phone_field/assets/flags/ky.png": "38e39eba673e82c48a1f25bd103a7e97",
"assets/packages/window_manager/images/ic_chrome_close.png": "75f4b8ab3608a05461a31fc18d6b47c2",
"assets/packages/window_manager/images/ic_chrome_minimize.png": "4282cd84cb36edf2efb950ad9269ca62",
"assets/packages/window_manager/images/ic_chrome_maximize.png": "af7499d7657c8b69d23b85156b60298c",
"assets/packages/window_manager/images/ic_chrome_unmaximize.png": "4a90c1909cb74e8f0d35794e2f61d8bf",
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "3759b2f7a51e83c64a58cfe07b96a8ee",
"assets/shaders/ink_sparkle.frag": "ecc85a2e95f5e9f53123dcaf8cb9b6ce",
"assets/AssetManifest.bin.json": "611449d46e56c96b3baef404bfc56246",
"assets/fonts/MaterialIcons-Regular.otf": "a57618538ab8b4c4081d4491870ac333",
"assets/assets/images/logo_light.png": "e5f46d5a78e226e7a9553d4ca6f69219",
"assets/assets/images/logo_dark.png": "a233ed1d4d0f7414bf97a9a10f11fb0a",
"assets/assets/images/payment_types/carteblanche.png": "d936e11fa3884b8c9f1bd5c914be8629",
"assets/assets/images/payment_types/mastercard.png": "6f6cdc29ee2e22e06b1ac029cb52ef71",
"assets/assets/images/payment_types/ach.png": "7433f0aff779dc98a649b7a2daf777cf",
"assets/assets/images/payment_types/maestro.png": "e533b92bfb50339fdbfa79e3dfe81f08",
"assets/assets/images/payment_types/visa.png": "3ddc4a4d25c946e8ad7e6998f30fd4e3",
"assets/assets/images/payment_types/other.png": "d936e11fa3884b8c9f1bd5c914be8629",
"assets/assets/images/payment_types/switch.png": "4fa11c45327f5fdc20205821b2cfd9cc",
"assets/assets/images/payment_types/unionpay.png": "7002f52004e0ab8cc0b7450b0208ccb2",
"assets/assets/images/payment_types/discover.png": "6c0a386a00307f87db7bea366cca35f5",
"assets/assets/images/payment_types/amex.png": "c49a4247984b3732a4af50a3390aa978",
"assets/assets/images/payment_types/paypal.png": "8e06c094c1871376dfea1da8088c29d1",
"assets/assets/images/payment_types/dinerscard.png": "06d85186ba858c18ab7c9caa42c92024",
"assets/assets/images/payment_types/jcb.png": "07e0942d16c5592118b72e74f2f7198c",
"assets/assets/images/payment_types/solo.png": "2030c3ccaccf5d5e87916a62f5b084d6",
"assets/assets/images/payment_types/laser.png": "b4e6e93dd35517ac429301119ff05868",
"assets/assets/images/google_logo.png": "0f118259ce403274f407f5e982e681c3",
"assets/assets/images/icon.png": "090f69e23311a4b6d851b3880ae52541",
"assets/assets/google_fonts/Roboto-Regular.ttf": "8a36205bd9b83e03af0591a004bc97f4",
"assets/NOTICES": "412b336cf9e33e70058d612857effae1",
"assets/AssetManifest.bin": "bf3be26e7055ad9a32f66b3a56138224",
"assets/FontManifest.json": "087fb858dc3cbfbf6baf6a30004922f1",
"flutter.js": "c71a09214cb6f5f8996a531350400a9a"};
// The application shell files that are downloaded before a service worker can // The application shell files that are downloaded before a service worker can
// start. // start.
const CORE = ["main.dart.js", const CORE = ["main.dart.js",

176259
public/main.dart.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

174895
public/main.foss.dart.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -171,15 +171,10 @@ class SquareCreditCard {
document.querySelector('input[name=token]').value = ''; document.querySelector('input[name=token]').value = '';
}); });
// let toggleWithToken = document.querySelector(
// '.toggle-payment-with-token'
// );
// if (!toggleWithToken) {
document.getElementById('loader').classList.add('hidden'); document.getElementById('loader').classList.add('hidden');
document.getElementById('payment-list').classList.remove('hidden'); document.getElementById('payment-list').classList.remove('hidden');
document.getElementById('toggle-payment-with-credit-card')?.click(); document.getElementById('toggle-payment-with-credit-card')?.click();
// }
}); });
} }

View File

@ -1,5 +1,18 @@
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' => '']) @extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' => ''])
@php
$gateway_instance = $gateway instanceof \App\Models\CompanyGateway ? $gateway : $gateway->company_gateway;
$token_billing_string = 'true';
if($gateway_instance->token_billing == 'off' || $gateway_instance->token_billing == 'optin'){
$token_billing_string = 'false';
}
if (isset($pre_payment) && $pre_payment == '1' && isset($is_recurring) && $is_recurring == '1') {
$token_billing_string = 'true';
}
@endphp
@section('gateway_head') @section('gateway_head')
@endsection @endsection
@ -12,7 +25,7 @@
<input type="hidden" name="gateway_type_id" id="gateway_type_id" value="{{ $gateway_type_id }}"> <input type="hidden" name="gateway_type_id" id="gateway_type_id" value="{{ $gateway_type_id }}">
<input type="hidden" name="gateway_response" id="gateway_response"> <input type="hidden" name="gateway_response" id="gateway_response">
<input type="hidden" name="amount_with_fee" id="amount_with_fee" value="{{ $total['amount_with_fee'] }}"/> <input type="hidden" name="amount_with_fee" id="amount_with_fee" value="{{ $total['amount_with_fee'] }}"/>
<input type="hidden" name="store_card" id="store_card"> <input type="hidden" name="store_card" id="store_card" value="{{ $token_billing_string }}">
<input type="hidden" name="token" value="" id="token"> <input type="hidden" name="token" value="" id="token">
</form> </form>
@ -44,6 +57,7 @@
<div id="checkout-form"> <div id="checkout-form">
<!-- Containers for Card Fields hosted by PayPal --> <!-- Containers for Card Fields hosted by PayPal -->
<div id="card-number-field-container"></div> <div id="card-number-field-container"></div>
<div id="card-name-field-container"></div>
<div class="expcvv" style="display:flex;"> <div class="expcvv" style="display:flex;">
<div id="card-expiry-field-container" style="width:50%"></div> <div id="card-expiry-field-container" style="width:50%"></div>
<div id="card-cvv-field-container" style="width:50%"></div> <div id="card-cvv-field-container" style="width:50%"></div>
@ -62,8 +76,12 @@
@push('footer') @push('footer')
<link rel="stylesheet" type="text/css" href=https://www.paypalobjects.com/webstatic/en_US/developer/docs/css/cardfields.css /> <link rel="stylesheet" type="text/css" href=https://www.paypalobjects.com/webstatic/en_US/developer/docs/css/cardfields.css />
<script src="https://www.paypal.com/sdk/js?client-id={!! $client_id !!}&components=card-fields" data-partner-attribution-id="invoiceninja_SP_PPCP"></script>
@if(isset($merchantId))
<script src="https://www.paypal.com/sdk/js?client-id={!! $client_id !!}&merchantId={!! $merchantId !!}&components=card-fields" data-partner-attribution-id="invoiceninja_SP_PPCP"></script>
@else
<script src="https://www.paypal.com/sdk/js?client-id={!! $client_id !!}&components=card-fields" data-partner-attribution-id="invoiceninja_SP_PPCP"></script>
@endif
<script> <script>
const clientId = "{{ $client_id }}"; const clientId = "{{ $client_id }}";
@ -129,9 +147,6 @@
}, },
onError: function(error) { onError: function(error) {
// console.log("on error")
// console.log(error);
document.getElementById('errors').textContent = `Sorry, your transaction could not be processed...\n\n${error.message}`; document.getElementById('errors').textContent = `Sorry, your transaction could not be processed...\n\n${error.message}`;
document.getElementById('errors').hidden = false; document.getElementById('errors').hidden = false;
@ -144,6 +159,9 @@
// Render each field after checking for eligibility // Render each field after checking for eligibility
if (cardField.isEligible()) { if (cardField.isEligible()) {
const nameField = cardField.NameField();
nameField.render("#card-name-field-container");
const numberField = cardField.NumberField({ const numberField = cardField.NumberField({
inputEvents: { inputEvents: {
@ -152,6 +170,7 @@
} }
}, },
}); });
numberField.render("#card-number-field-container"); numberField.render("#card-number-field-container");
const cvvField = cardField.CVVField({ const cvvField = cardField.CVVField({

View File

@ -12,6 +12,8 @@
namespace Tests\Integration\Einvoice; namespace Tests\Integration\Einvoice;
use Tests\TestCase; use Tests\TestCase;
use Sabre\Xml\Reader;
use Sabre\Xml\Service;
use Invoiceninja\Einvoice\Models\FACT1\Invoice; use Invoiceninja\Einvoice\Models\FACT1\Invoice;
/** /**
@ -20,54 +22,182 @@ use Invoiceninja\Einvoice\Models\FACT1\Invoice;
class FACT1Test extends TestCase class FACT1Test extends TestCase
{ {
public array $set = [];
protected function setUp(): void protected function setUp(): void
{ {
parent::setUp(); parent::setUp();
} }
public function testValidationFact1() public function testValidationFact1()
{ {
$files = [ $files = [
'tests/Integration/Einvoice/samples/fact1.xml', 'tests/Integration/Einvoice/samples/fact1_no_prefixes.xml',
]; ];
foreach($files as $f) { foreach($files as $f) {
$xmlstring = file_get_contents($f); $xml = file_get_contents($f);
// nlog($xmlstring); $xml = simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA);
$xml = simplexml_load_string($xmlstring, "SimpleXMLElement");
$json = json_encode($xml); $json = json_encode($xml);
$payload = json_decode($json, true); $array = json_decode($json, true);
nlog($xml); $i = Invoice::from($array);
nlog($payload);
$validation_array = false; $rules = Invoice::getValidationRules($array);
try {
$rules = Invoice::getValidationRules($payload);
nlog($rules);
$this->assertIsArray($rules); $this->assertIsArray($rules);
$payload = Invoice::from($payload)->toArray();
nlog($payload);
$this->assertIsArray($payload);
$validation_array = Invoice::validate($payload); $validation_array = Invoice::validate($array);
$this->assertIsArray($validation_array);
} catch(\Illuminate\Validation\ValidationException $e) {
nlog($e->errors());
}
$this->assertIsArray($validation_array); $this->assertIsArray($validation_array);
} }
} }
public function removeNamespacesFromArray($data)
{
if (is_array($data)) {
foreach ($data as &$item) {
if (isset($item['name'])) {
// Remove the namespace from the name
$item['name'] = preg_replace('/^\{\}(.+)/', '$1', $item['name']);
}
if (isset($item['value']) && is_array($item['value'])) {
// Recursively process child elements
$item['value'] = $this->removeNamespacesFromArray($item['value']);
}
if (isset($item['attributes'])) {
unset($item['attributes']);
}
}
}
return $data;
}
// function convertToKeyValue($data)
// {
// $result = [];
// foreach ($data as $item) {
// // Remove namespace prefix if present
// $name = preg_replace('/^\{\}(.+)/', '$1', $item['name']);
// $result[$name] = $item['value'];
// }
// return $result;
// }
// public function keyValueDeserializer(Reader $reader)
// {
// $values = [];
// $reader->read();
// $reader->next();
// foreach ($reader->parseGetElements() as $element) {
// // Strip the namespace prefix
// echo "merp".PHP_EOL;
// $name = preg_replace('/^\{\}.*/', '', $element['name']);
// $values[$name] = $element['value'];
// }
// return $values;
// }
// public function testFactToArray()
// {
// $xml = file_get_contents('tests/Integration/Einvoice/samples/fact1_no_prefixes.xml');
// $service = new Service();
// // $service->elementMap = [
// // '{}' => 'Sabre\Xml\Deserializer\keyValue',
// // ];
// // $service->elementMap = [
// // '{}*' => function (Reader $reader) use ($service) {
// // return $this->keyValueDeserializer($reader);
// // }
// // ];
// $result = $this->removeNamespacesFromArray($service->parse($xml));
// // Convert parsed XML to key-value array
// if (isset($result['value']) && is_array($result['value'])) {
// $keyValueArray = $this->convertToKeyValue($result['value']);
// } else {
// $keyValueArray = [];
// }
// // Output the result
// nlog($keyValueArray);
// // nlog($cleanedArray);
// nlog($service->parse($xml));
// }
// Output the result
// ($xmlWithoutNamespaces);
// $reader = new Reader();
// $service = new Service();
// $service->elementMap = [
// '*' => 'Sabre\Xml\Deserializer\keyValue',
// ];
// nlog($service->parse($xmlstring));
// $payload ='';
// // $reader->xml($xmlstring);
// // $payload = $reader->parse();
// // nlog($payload);
// $validation_array = false;
// try {
// $rules = Invoice::getValidationRules($payload);
// nlog($rules);
// $this->assertIsArray($rules);
// $payload = Invoice::from($payload)->toArray();
// nlog($payload);
// $this->assertIsArray($payload);
// $validation_array = Invoice::validate($payload);
// $this->assertIsArray($validation_array);
// } catch(\Illuminate\Validation\ValidationException $e) {
// nlog($e->errors());
// }
// $this->assertIsArray($validation_array);
// }
// private function extractName($name): string
// {
// $pattern = '/\{[^{}]*\}([^{}]*)/';
// if (preg_match($pattern, $name, $matches)) {
// $extracted = $matches[1];
// return $extracted;
// }
// return $name;
// }
} }

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,113 @@
<?xml version="1.0"?>
<Invoice>
<UBLVersionID>2.1</UBLVersionID>
<CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:efactura.mfinante.ro:CIUS-RO:1.0.1</CustomizationID>
<ID>ABC 0020</ID>
<IssueDate>2024-01-01</IssueDate>
<DueDate>2024-01-15</DueDate>
<InvoiceTypeCode>384</InvoiceTypeCode>
<DocumentCurrencyCode>RON</DocumentCurrencyCode>
<TaxCurrencyCode>RON</TaxCurrencyCode>
<AccountingSupplierParty>
<Party>
<PartyIdentification>
<ID>234234234</ID>
</PartyIdentification>
<PostalAddress>
<StreetName>This can be the full address , not just the street and street nr.</StreetName>
<CityName>SECTOR2</CityName>
<CountrySubentity>RO-B</CountrySubentity>
<Country>
<IdentificationCode>RO</IdentificationCode>
</Country>
</PostalAddress>
<PartyTaxScheme>
<CompanyID>RO234234234</CompanyID>
<TaxScheme>
<ID>VAT</ID>
</TaxScheme>
</PartyTaxScheme>
<PartyLegalEntity>
<RegistrationName>Some Copany Name</RegistrationName>
<CompanyID>J40/2222/2009</CompanyID>
</PartyLegalEntity>
<Contact>
<Name>Someone</Name>
<Telephone>88282819832</Telephone>
<ElectronicMail>some@email.com</ElectronicMail>
</Contact>
</Party>
</AccountingSupplierParty>
<AccountingCustomerParty>
<Party>
<PartyIdentification>
<ID>646546549</ID>
</PartyIdentification>
<PostalAddress>
<StreetName>This can be the full address , not just the street and street nr.</StreetName>
<CityName>SECTOR3</CityName>
<CountrySubentity>RO-B</CountrySubentity>
<Country>
<IdentificationCode>RO</IdentificationCode>
</Country>
</PostalAddress>
<PartyLegalEntity>
<RegistrationName>Some Comapny</RegistrationName>
<CompanyID>646546549</CompanyID>
</PartyLegalEntity>
<Contact>
<Name>Someone</Name>
<Telephone>88282819832</Telephone>
<ElectronicMail>some@email.com</ElectronicMail>
</Contact>
</Party>
</AccountingCustomerParty>
<PaymentMeans>
<PaymentMeansCode>42</PaymentMeansCode>
<PayeeFinancialAccount>
<ID>some account nr</ID>
<Name>Bank name</Name>
</PayeeFinancialAccount>
</PaymentMeans>
<TaxTotal>
<TaxAmount currencyID="RON">63.65</TaxAmount>
<TaxSubtotal>
<TaxableAmount currencyID="RON">335.00</TaxableAmount>
<TaxAmount currencyID="RON">63.65</TaxAmount>
<TaxCategory>
<ID>S</ID> // this is a speciffic identifier for the VAT type <Percent>
19</Percent>
<TaxScheme>
<ID>VAT</ID>
</TaxScheme>
</TaxCategory>
</TaxSubtotal>
</TaxTotal>
<LegalMonetaryTotal>
<LineExtensionAmount currencyID="RON">335.00</LineExtensionAmount>
<TaxExclusiveAmount currencyID="RON">335.00</TaxExclusiveAmount>
<TaxInclusiveAmount currencyID="RON">398.65</TaxInclusiveAmount>
<AllowanceTotalAmount currencyID="RON">0.00</AllowanceTotalAmount>
<PayableAmount currencyID="RON">398.65</PayableAmount>
</LegalMonetaryTotal>
<InvoiceLine>
<ID>1</ID>
<InvoicedQuantity unitCode="H87">1</InvoicedQuantity> // unitcode is a speciffic
identifier for the type of product <LineExtensionAmount currencyID="RON">
335.00</LineExtensionAmount>
<Item>
<Description>Some Description</Description>
<Name>Some product</Name>
<ClassifiedTaxCategory>
<ID>S</ID> // this is a speciffic identifier for the VAT type <Percent>
19</Percent>
<TaxScheme>
<ID>VAT</ID>
</TaxScheme>
</ClassifiedTaxCategory>
</Item>
<Price>
<PriceAmount currencyID="RON">335</PriceAmount>
</Price>
</InvoiceLine>
</Invoice>