diff --git a/app/Console/Commands/CreateSingleAccount.php b/app/Console/Commands/CreateSingleAccount.php index eb9395c1b152..cfdf4177798d 100644 --- a/app/Console/Commands/CreateSingleAccount.php +++ b/app/Console/Commands/CreateSingleAccount.php @@ -11,53 +11,54 @@ namespace App\Console\Commands; -use App\DataMapper\ClientRegistrationFields; -use App\DataMapper\CompanySettings; -use App\DataMapper\FeesAndLimits; -use App\Events\Invoice\InvoiceWasCreated; -use App\Events\RecurringInvoice\RecurringInvoiceWasCreated; -use App\Factory\GroupSettingFactory; -use App\Factory\InvoiceFactory; -use App\Factory\InvoiceItemFactory; -use App\Factory\RecurringInvoiceFactory; -use App\Factory\SubscriptionFactory; -use App\Helpers\Invoice\InvoiceSum; -use App\Jobs\Company\CreateCompanyTaskStatuses; -use App\Libraries\MultiDB; -use App\Models\Account; -use App\Models\BankIntegration; -use App\Models\BankTransaction; -use App\Models\BankTransactionRule; +use stdClass; +use Carbon\Carbon; +use Faker\Factory; +use App\Models\Task; +use App\Models\User; +use App\Utils\Ninja; +use App\Models\Quote; use App\Models\Client; -use App\Models\ClientContact; -use App\Models\Company; -use App\Models\CompanyGateway; -use App\Models\CompanyToken; -use App\Models\Country; use App\Models\Credit; +use App\Models\Vendor; +use App\Models\Account; +use App\Models\Company; +use App\Models\Country; use App\Models\Expense; use App\Models\Invoice; use App\Models\Product; use App\Models\Project; -use App\Models\Quote; -use App\Models\RecurringInvoice; -use App\Models\Task; -use App\Models\TaskStatus; use App\Models\TaxRate; -use App\Models\User; -use App\Models\Vendor; +use App\Libraries\MultiDB; +use App\Models\TaskStatus; +use App\Models\CompanyToken; +use App\Models\ClientContact; use App\Models\VendorContact; -use App\Repositories\InvoiceRepository; -use App\Utils\Ninja; -use App\Utils\Traits\GeneratesCounter; +use App\Models\CompanyGateway; +use App\Factory\InvoiceFactory; +use App\Models\BankIntegration; +use App\Models\BankTransaction; use App\Utils\Traits\MakesHash; -use Carbon\Carbon; -use Faker\Factory; use Illuminate\Console\Command; -use Illuminate\Support\Facades\Cache; +use App\Models\RecurringInvoice; +use App\DataMapper\FeesAndLimits; +use App\DataMapper\ClientSettings; +use App\DataMapper\CompanySettings; +use App\Factory\InvoiceItemFactory; +use App\Helpers\Invoice\InvoiceSum; +use App\Models\BankTransactionRule; +use App\Factory\GroupSettingFactory; +use App\Factory\SubscriptionFactory; use Illuminate\Support\Facades\Hash; +use Illuminate\Support\Facades\Cache; +use App\Utils\Traits\GeneratesCounter; use Illuminate\Support\Facades\Schema; -use stdClass; +use App\Repositories\InvoiceRepository; +use App\Factory\RecurringInvoiceFactory; +use App\Events\Invoice\InvoiceWasCreated; +use App\DataMapper\ClientRegistrationFields; +use App\Jobs\Company\CreateCompanyTaskStatuses; +use App\Events\RecurringInvoice\RecurringInvoiceWasCreated; class CreateSingleAccount extends Command { @@ -951,7 +952,7 @@ class CreateSingleAccount extends Command } - if (config('ninja.testvars.paytrace.decrypted') && ($this->gateway == 'all' || $this->gateway == 'paytrace')) { + if (config('ninja.testvars.paytrace') && ($this->gateway == 'all' || $this->gateway == 'paytrace')) { $cg = new CompanyGateway(); $cg->company_id = $company->id; $cg->user_id = $user->id; @@ -960,7 +961,7 @@ class CreateSingleAccount extends Command $cg->require_billing_address = true; $cg->require_shipping_address = true; $cg->update_details = true; - $cg->config = encrypt(config('ninja.testvars.paytrace.decrypted')); + $cg->config = encrypt(config('ninja.testvars.paytrace')); $cg->save(); @@ -1015,6 +1016,63 @@ class CreateSingleAccount extends Command $cg->fees_and_limits = $fees_and_limits; $cg->save(); } + + if (config('ninja.testvars.eway') && ($this->gateway == 'all' || $this->gateway == 'eway')) { + $cg = new CompanyGateway(); + $cg->company_id = $company->id; + $cg->user_id = $user->id; + $cg->gateway_key = '944c20175bbe6b9972c05bcfe294c2c7'; + $cg->require_cvv = true; + $cg->require_billing_address = true; + $cg->require_shipping_address = true; + $cg->update_details = true; + $cg->config = encrypt(config('ninja.testvars.eway')); + $cg->save(); + + $gateway_types = $cg->driver()->gatewayTypes(); + + $fees_and_limits = new stdClass(); + $fees_and_limits->{$gateway_types[0]} = new FeesAndLimits(); + + $cg->fees_and_limits = $fees_and_limits; + $cg->save(); + } + + + if (config('ninja.testvars.gocardless') && ($this->gateway == 'all' || $this->gateway == 'gocardless')) { + + $c_settings = ClientSettings::defaults(); + $c_settings->currency_id = '2'; + + $client = Client::factory()->create([ + 'user_id' => $user->id, + 'company_id' => $company->id, + 'name' => 'cypress', + 'country_id' => 826, + 'settings' => $c_settings + ]); + + $cg = new CompanyGateway(); + $cg->company_id = $company->id; + $cg->user_id = $user->id; + $cg->gateway_key = 'b9886f9257f0c6ee7c302f1c74475f6c'; + $cg->require_cvv = true; + $cg->require_billing_address = true; + $cg->require_shipping_address = true; + $cg->update_details = true; + $cg->config = encrypt(config('ninja.testvars.gocardless')); + $cg->save(); + + $gateway_types = $cg->driver($client)->gatewayTypes(); + + $fees_and_limits = new stdClass(); + $fees_and_limits->{$gateway_types[0]} = new FeesAndLimits(); + + $cg->fees_and_limits = $fees_and_limits; + $cg->save(); + } + + } private function createRecurringInvoice(Client $client) diff --git a/app/Http/Controllers/CompanyGatewayController.php b/app/Http/Controllers/CompanyGatewayController.php index 732787b2d317..ec7c32cc78e6 100644 --- a/app/Http/Controllers/CompanyGatewayController.php +++ b/app/Http/Controllers/CompanyGatewayController.php @@ -23,6 +23,7 @@ use App\Http\Requests\CompanyGateway\StoreCompanyGatewayRequest; use App\Http\Requests\CompanyGateway\TestCompanyGatewayRequest; use App\Http\Requests\CompanyGateway\UpdateCompanyGatewayRequest; use App\Jobs\Util\ApplePayDomain; +use App\Libraries\MultiDB; use App\Models\Client; use App\Models\CompanyGateway; use App\PaymentDrivers\CheckoutCom\CheckoutSetupWebhook; @@ -544,4 +545,15 @@ class CompanyGatewayController extends BaseController } + public function importCustomers(TestCompanyGatewayRequest $request, CompanyGateway $company_gateway) + { + + dispatch(function () use($company_gateway) { + MultiDB::setDb($company_gateway->company->db); + $company_gateway->driver()->importCustomers(); + })->afterResponse(); + + return response()->json(['message' => ctrans('texts.import_started')], 200); + } + } diff --git a/app/Models/Account.php b/app/Models/Account.php index 4fc236da4971..adf95c62086f 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -494,7 +494,7 @@ class Account extends BaseModel return 0; } - if (Carbon::createFromTimestamp($this->created_at)->diffInWeeks() == 0) { + if (Carbon::createFromTimestamp($this->created_at)->diffInWeeks() <= 1) { return 20; } diff --git a/app/Models/CompanyGateway.php b/app/Models/CompanyGateway.php index 253af5585fe6..aa8f0438e5a2 100644 --- a/app/Models/CompanyGateway.php +++ b/app/Models/CompanyGateway.php @@ -132,6 +132,7 @@ class CompanyGateway extends BaseModel // const TYPE_EWAY = 313; // const TYPE_FORTE = 314; // const PAYPAL_PPCP = 323; + // const SQUARE = 320; public $gateway_consts = [ '38f2c48af60c7dd69e04248cbb24c36e' => 300, @@ -144,7 +145,7 @@ class CompanyGateway extends BaseModel '8fdeed552015b3c7b44ed6c8ebd9e992' => 309, 'd6814fc83f45d2935e7777071e629ef9' => 310, 'bbd736b3254b0aabed6ad7fda1298c88' => 311, - '1bd651fb213ca0c9d66ae3c336dc77e7' => 312, + '1bd651fb213ca0c9d66ae3c336dc77e8' => 312, '944c20175bbe6b9972c05bcfe294c2c7' => 313, 'kivcvjexxvdiyqtj3mju5d6yhpeht2xs' => 314, '65faab2ab6e3223dbe848b1686490baz' => 320, diff --git a/app/PaymentDrivers/AuthorizePaymentDriver.php b/app/PaymentDrivers/AuthorizePaymentDriver.php index 861df0c50993..87c74fdb9209 100644 --- a/app/PaymentDrivers/AuthorizePaymentDriver.php +++ b/app/PaymentDrivers/AuthorizePaymentDriver.php @@ -193,9 +193,16 @@ class AuthorizePaymentDriver extends BaseDriver public function import() { + $this->init(); + return (new AuthorizeCustomer($this))->importCustomers(); } + public function importCustomers() + { + return $this->import(); + } + public function auth(): bool { return $this->init()->getPublicClientKey() ?? false; diff --git a/app/PaymentDrivers/BaseDriver.php b/app/PaymentDrivers/BaseDriver.php index 5739a8d08321..a8ffd38cd61e 100644 --- a/app/PaymentDrivers/BaseDriver.php +++ b/app/PaymentDrivers/BaseDriver.php @@ -811,4 +811,9 @@ class BaseDriver extends AbstractPaymentDriver { return true; } + + public function importCustomers() + { + + } } diff --git a/app/PaymentDrivers/BraintreePaymentDriver.php b/app/PaymentDrivers/BraintreePaymentDriver.php index ec64d62f9a5f..23d067424c9d 100644 --- a/app/PaymentDrivers/BraintreePaymentDriver.php +++ b/app/PaymentDrivers/BraintreePaymentDriver.php @@ -12,29 +12,39 @@ namespace App\PaymentDrivers; -use App\Jobs\Util\SystemLogger; -use App\Models\ClientGatewayToken; -use App\Models\GatewayType; +use Exception; +use App\Models\Client; +use Braintree\Gateway; use App\Models\Invoice; use App\Models\Payment; +use App\Models\SystemLog; +use App\Models\GatewayType; use App\Models\PaymentHash; use App\Models\PaymentType; -use App\Models\SystemLog; +use App\Models\ClientContact; +use App\Factory\ClientFactory; +use App\Jobs\Util\SystemLogger; +use App\Models\ClientGatewayToken; +use App\Factory\ClientContactFactory; use App\PaymentDrivers\Braintree\ACH; -use App\PaymentDrivers\Braintree\CreditCard; +use App\Utils\Traits\GeneratesCounter; +use Illuminate\Database\QueryException; use App\PaymentDrivers\Braintree\PayPal; -use Braintree\Gateway; -use Exception; use Illuminate\Support\Facades\Validator; +use App\PaymentDrivers\Braintree\CreditCard; class BraintreePaymentDriver extends BaseDriver { + use GeneratesCounter; + public $refundable = true; public $token_billing = true; public $can_authorise_credit_card = true; + private bool $completed = true; + /** * @var Gateway; */ @@ -304,7 +314,7 @@ class BraintreePaymentDriver extends BaseDriver try { $ct =$this->init()->gateway->clientToken()->generate(); - nlog($ct); + return true; } catch(\Exception $e) { @@ -313,4 +323,165 @@ class BraintreePaymentDriver extends BaseDriver return false; } + + private function find(string $customer_id = '') { + + try { + return $this->init()->gateway->customer()->find($customer_id); + } + catch(\Exception $e){ + return false; + } + + return false; + } + + private function findTokens(string $gateway_customer_reference) + { + return ClientGatewayToken::where('company_id', $this->company_gateway->company_id) + ->where('gateway_customer_reference', $gateway_customer_reference) + ->exists(); + } + + private function findContact(string $email) { + return ClientContact::where('company_id', $this->company_gateway->company_id) + ->where('email', $email) + ->first()->client ?? false; + } + + private function addClientCards(Client $client, array $cards) + { + + $this->client = $client; + + foreach($cards as $card) { + + $payment_meta = new \stdClass(); + $payment_meta->exp_month = (string) $card->expirationMonth; + $payment_meta->exp_year = (string) $card->expirationYear; + $payment_meta->brand = (string) $card->cardType; + $payment_meta->last4 = (string) $card->last4; + $payment_meta->type = GatewayType::CREDIT_CARD; + + $data = [ + 'payment_meta' => $payment_meta, + 'token' => $card->token, + 'payment_method_id' => GatewayType::CREDIT_CARD, + ]; + + $this->storeGatewayToken($data, ['gateway_customer_reference' => $card->customerId]); + + nlog("adding card to customer payment profile"); + + } + + } + + public function createNinjaClient(mixed $customer): Client + { + + $client = ClientFactory::create($this->company_gateway->company_id, $this->company_gateway->user_id); + + $b_business_address = count($customer->addresses) >= 1 ? $customer->addresses[0] : false; + $b_shipping_address = count($customer->addresses) > 1 ? $customer->addresses[1] : false; + $import_client_data = []; + + if($b_business_address) { + + $braintree_address = + [ + 'address1' => $b_business_address->extendedAddress ?? '', + 'address2' => $b_business_address->streetAddress ?? '', + 'city' => $b_business_address->locality ?? '', + 'postal_code' => $b_business_address->postalCode ?? '', + 'state' => $b_business_address->region ?? '', + 'country_id' => $b_business_address->countryCodeNumeric ?? '840', + ]; + + $import_client_data = array_merge($import_client_data, $braintree_address); + } + + if($b_shipping_address) { + + $braintree_shipping_address = + [ + 'shipping_address1' => $b_shipping_address->extendedAddress ?? '', + 'shipping_address2' => $b_shipping_address->streetAddress ?? '', + 'shipping_city' => $b_shipping_address->locality ?? '', + 'shipping_postal_code' => $b_shipping_address->postalCode ?? '', + 'shipping_state' => $b_shipping_address->region ?? '', + 'shipping_country_id' => $b_shipping_address->countryCodeNumeric ?? '840', + ]; + + $import_client_data = array_merge($import_client_data, $braintree_shipping_address); + + } + + $client->fill($import_client_data); + + $client->phone = $customer->phone ?? ''; + $client->name = $customer->company ?? $customer->firstName; + + $settings = $client->settings; + $settings->currency_id = (string) $this->company_gateway->company->settings->currency_id; + $client->settings = $settings; + $client->save(); + + $contact = ClientContactFactory::create($this->company_gateway->company_id, $this->company_gateway->user_id); + $contact->first_name = $customer->firstName ?? ''; + $contact->last_name = $customer->lastName ?? ''; + $contact->email = $customer->email ?? ''; + $contact->phone = $customer->phone ?? ''; + $contact->client_id = $client->id; + $contact->saveQuietly(); + + if (! isset($client->number) || empty($client->number)) { + $x = 1; + + do { + try { + $client->number = $this->getNextClientNumber($client); + $client->saveQuietly(); + + $this->completed = false; + } catch (QueryException $e) { + $x++; + + if ($x > 10) { + $this->completed = false; + } + } + } while ($this->completed); + } else { + $client->saveQuietly(); + } + + return $client; + + } + + public function importCustomers() + { + $customers = $this->init()->gateway->customer()->all(); + + foreach($customers as $c){ + + $customer = $this->find($c->id); + + if(!$customer) + continue; + + if(!$this->findTokens($c->id) && !($client = $this->findContact($customer->email))) { + //customer is not referenced in the system - create client + $client = $this->createNinjaClient($customer); + nlog("Creating new Client"); + } + + + $this->addClientCards($client, $customer->creditCards); + + nlog("Adding Braintree Client: {$c->id} => {$client->id}"); + + } + } } diff --git a/app/PaymentDrivers/GoCardlessPaymentDriver.php b/app/PaymentDrivers/GoCardlessPaymentDriver.php index afd08c49a6aa..723a190f00be 100644 --- a/app/PaymentDrivers/GoCardlessPaymentDriver.php +++ b/app/PaymentDrivers/GoCardlessPaymentDriver.php @@ -84,11 +84,11 @@ class GoCardlessPaymentDriver extends BaseDriver $types[] = GatewayType::DIRECT_DEBIT; } - if (in_array($this->client->currency()->code, ['EUR', 'GBP'])) { + if ($this->client && in_array($this->client->currency()->code, ['EUR', 'GBP'])) { $types[] = GatewayType::SEPA; } - if ($this->client->currency()->code === 'GBP') { + if ($this->client && $this->client->currency()->code === 'GBP') { $types[] = GatewayType::INSTANT_BANK_PAY; } diff --git a/app/PaymentDrivers/Stripe/ImportCustomers.php b/app/PaymentDrivers/Stripe/ImportCustomers.php index 6001ed84298e..aa874444398d 100644 --- a/app/PaymentDrivers/Stripe/ImportCustomers.php +++ b/app/PaymentDrivers/Stripe/ImportCustomers.php @@ -62,12 +62,6 @@ class ImportCustomers $this->addCustomer($customer); } - //handle - // if(is_array($customers->data) && end($customers->data) && array_key_exists('id', end($customers->data))) - // $starting_after = end($customers->data)['id']; - // else - // break; - $starting_after = isset(end($customers->data)['id']) ? end($customers->data)['id'] : false; if (!$starting_after) { diff --git a/config/ninja.php b/config/ninja.php index 47ecd5b1aa42..98a742d15c6d 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -84,6 +84,11 @@ return [ 'username' => 'user@example.com', 'clientname' => 'client@example.com', 'password' => 'password', + 'gocardless' => env('GOCARDLESS_KEYS',''), + 'square' => env('SQUARE_KEYS',''), + 'eway' => env('EWAY_KEYS',''), + 'mollie', env('MOLLIE_KEYS',''), + 'paytrace' => env('PAYTRACE_KEYS',''), 'stripe' => env('STRIPE_KEYS', ''), 'paypal' => env('PAYPAL_KEYS', ''), 'ppcp' => env('PPCP_KEYS', ''), @@ -94,11 +99,6 @@ return [ 'test_email' => env('TEST_EMAIL', 'test@example.com'), 'wepay' => env('WEPAY_KEYS', ''), 'braintree' => env('BRAINTREE_KEYS', ''), - 'paytrace' => [ - 'username' => env('PAYTRACE_U', ''), - 'password' => env('PAYTRACE_P', ''), - 'decrypted' => env('PAYTRACE_KEYS', ''), - ], 'mollie' => env('MOLLIE_KEYS', ''), 'square' => env('SQUARE_KEYS', ''), ], diff --git a/routes/api.php b/routes/api.php index bf2be5dcbb0b..92596e03d8cb 100644 --- a/routes/api.php +++ b/routes/api.php @@ -198,6 +198,7 @@ Route::group(['middleware' => ['throttle:api', 'api_db', 'token_auth', 'locale'] Route::post('company_gateways/bulk', [CompanyGatewayController::class, 'bulk'])->name('company_gateways.bulk'); Route::post('company_gateways/{company_gateway}/test', [CompanyGatewayController::class, 'test'])->name('company_gateways.test'); + Route::post('company_gateways/{company_gateway}/import_customers', [CompanyGatewayController::class, 'importCustomers'])->name('company_gateways.import_customers'); Route::put('company_users/{user}', [CompanyUserController::class, 'update']); Route::put('company_users/{user}/preferences', [CompanyUserController::class, 'updatePreferences']);