Square factory

This commit is contained in:
David Bomba 2024-03-19 10:38:54 +11:00
parent 08e5d35955
commit 3ef7d68eed
11 changed files with 563 additions and 115 deletions

View File

@ -55,6 +55,9 @@ class CompanyGatewayController extends BaseController
private string $checkout_key = '3758e7f7c6f4cecf0f4f348b9a00f456';
private string $forte_key = 'kivcvjexxvdiyqtj3mju5d6yhpeht2xs';
/**
* CompanyGatewayController constructor.
* @param CompanyRepository $company_repo
@ -228,6 +231,13 @@ class CompanyGatewayController extends BaseController
StripeWebhook::dispatch($company_gateway->company->company_key, $company_gateway->id);
} elseif($company_gateway->gateway_key == $this->checkout_key) {
CheckoutSetupWebhook::dispatch($company_gateway->company->company_key, $company_gateway->id);
} elseif($company_gateway->gateway_key == $this->forte_key) {
dispatch(function () use ($company_gateway) {
MultiDB::setDb($company_gateway->company->db);
$company_gateway->driver()->updateFees();
})->afterResponse();
}
return $this->itemResponse($company_gateway);
@ -410,6 +420,13 @@ class CompanyGatewayController extends BaseController
if($company_gateway->gateway_key == $this->checkout_key) {
CheckoutSetupWebhook::dispatch($company_gateway->company->company_key, $company_gateway->fresh()->id);
}elseif($company_gateway->gateway_key == $this->forte_key){
dispatch(function () use ($company_gateway) {
MultiDB::setDb($company_gateway->company->db);
$company_gateway->driver()->updateFees();
})->afterResponse();
}
return $this->itemResponse($company_gateway);

View File

@ -31,10 +31,11 @@ class ForteCustomerFactory
'phone' => $this->getBillingAddress($customer)['phone'],
]
],
'currency_id' => $company->settings->currency_id,
])->merge($this->getBillingAddress($customer))
->merge($this->getShippingAddress($customer))
'settings' => [
'currency_id' => $company->settings->currency_id,
],
])->merge($this->getShippingAddress($customer))
->merge($this->getBillingAddress($customer))
->toArray();
}
@ -101,12 +102,12 @@ class ForteCustomerFactory
}
return [
'address1' => $address['physical_address']['street_line1'],
'address2' => $address['physical_address']['street_line2'],
'city' => $address['physical_address']['locality'],
'state' => $address['physical_address']['region'],
'postal_code' => $address['physical_address']['postal_code'],
'country_id' => '840',
'shipping_address1' => $address['physical_address']['street_line1'],
'shipping_address2' => $address['physical_address']['street_line2'],
'shipping_city' => $address['physical_address']['locality'],
'shipping_state' => $address['physical_address']['region'],
'shipping_postal_code' => $address['physical_address']['postal_code'],
'shipping_country_id' => '840',
];
}
@ -118,12 +119,14 @@ class ForteCustomerFactory
$address = $customer['addresses'][1];
return [
'address1' => $address['physical_address']['street_line1'],
'address2' => $address['physical_address']['street_line2'],
'city' => $address['physical_address']['locality'],
'state' => $address['physical_address']['region'],
'postal_code' => $address['physical_address']['postal_code'],
'country_id' => '840',
'shipping_address1' => $address['physical_address']['street_line1'],
'shipping_address2' => $address['physical_address']['street_line2'],
'shipping_city' => $address['physical_address']['locality'],
'shipping_state' => $address['physical_address']['region'],
'shipping_postal_code' => $address['physical_address']['postal_code'],
'shipping_country_id' => '840',
'email' => $address['email'],
'phone' => $address['phone'],
];
}

View File

@ -0,0 +1,59 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\PaymentDrivers\Factory;
use App\Models\Company;
class PaytraceCustomerFactory
{
public function convertToNinja($customer, Company $company): array
{
return
collect([
'name' => $customer->billing_address->name ?? $customer->shipping_address->name,
'contacts' => [
[
'first_name' => $customer->billing_address->name ?? $customer->shipping_address->name,
'last_name' => '',
'email' => $customer->email,
'phone' => $customer->phone,
]
],
'currency_id' => $company->settings->currency_id,
'address1' => $customer->billing_address->street_address,
'address2' => $customer->billing_address->street_address2,
'city' => $customer->billing_address->city,
'state' => $customer->billing_address->state,
'postal_code' => $customer->billing_address->zip,
'country_id' => '840',
'shipping_address1' => $customer->shipping_address->street_address,
'shipping_address2' => $customer->shipping_address->street_address2,
'shipping_city' => $customer->shipping_address->city,
'shipping_state' => $customer->shipping_address->state,
'shipping_postal_code' => $customer->shipping_address->zip,
'shipping_country_id' => '840',
'settings' => [
'currency_id' => $company->settings->currency_id,
],
'card' => [
'token' => $customer->customer_id,
'last4' => $customer->credit_card->masked_number,
'expiry_month' => $customer->credit_card->expiration_month,
'expiry_year' => $customer->credit_card->expiration_year,
],
])
->toArray();
}
}

View File

@ -0,0 +1,132 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\PaymentDrivers\Factory;
use App\Models\Company;
use App\Models\GatewayType;
class SquareCustomerFactory
{
/*
{
"id": "A537H7KAQWSAF8M8EM1Y23E16M",
"created_at": "2021-10-28T20:19:07.692Z",
"updated_at": "2024-01-09T20:14:21Z",
"cards": [
{
"id": "ccof:oG9wEmGAvoAnrBGt3GB",
"card_brand": "VISA",
"last_4": "5858",
"exp_month": 10,
"exp_year": 2023,
"cardholder_name": "Amelia Earhart",
"billing_address": {
"address_line_1": "500 Electric Ave",
"locality": "New York",
"administrative_district_level_1": "NY",
"postal_code": "94103",
"country": "US"
}
},
{
"id": "gftc:06c30c2b9772458a9e87b2880ee2ce1a",
"card_brand": "SQUARE_GIFT_CARD",
"last_4": "0895",
"exp_month": 12,
"exp_year": 2050,
"billing_address": {
"postal_code": "94103"
}
}
],
"given_name": "Amelia",
"family_name": "Earhart",
"email_address": "Amelia.Earhart@example.com",
"address": {
"address_line_1": "123 Main St",
"locality": "Seattle",
"administrative_district_level_1": "WA",
"postal_code": "98121",
"country": "US"
},
"phone_number": "1-212-555-4240",
"note": "a customer on seller account",
"reference_id": "YOUR_REFERENCE_ID",
"company_name": "ACME",
"preferences": {
"email_unsubscribed": false
},
"creation_source": "THIRD_PARTY",
"segment_ids": [
"8QJTJCE6AZSN6.REACHABLE",
"8QJTJCE6AZSN6.CARDS_ON_FILE",
"gv2:8H24YRM74H2030XWJWP9F0MAEW",
"gv2:4TR2NFVP8N63D9K1FZ5E62VD78"
],
"version": 4
},
*/
public function convertToNinja($customer, Company $company): array
{
$cards = [];
foreach($customer->getCards() ?? [] as $card){
$meta = new \stdClass;
$meta->exp_month = $card->getExpMonth();
$meta->exp_year = $card->getExpYear();
$meta->last4 = $card->getLast4();
$meta->brand = $card->getCardBrand();
$meta->type = GatewayType::CREDIT_CARD;
$cards[] = [
'token' => $card->getId(),
'payment_meta' => $meta,
'payment_method_id' => GatewayType::CREDIT_CARD,
'gateway_customer_reference' => $customer->getId(),
];
}
$address = $customer->getAddress();
return
collect([
'name' => $customer->getCompanyName() ?? ($customer->getGivenName() ?? '' ." " . $customer->getFamilyName() ?? ''),
'contacts' => [
[
'first_name' => $customer->getGivenName(),
'last_name' => $customer->getFamilyName(),
'email' => $customer->getEmailAddress(),
'phone' => $customer->getPhoneNumber(),
]
],
'currency_id' => $company->settings->currency_id,
'address1' => $address->getAddressLine1(),
'address2' => $address->getAddressLine2(),
'city' => $address->getLocality(),
'state' => $address->getAdministrativeDistrictLevel1(),
'postal_code' => $address->getPostalCode(),
'country_id' => '840',
'settings' => [
'currency_id' => $company->settings->currency_id,
],
'cards' => $cards,
])
->toArray();
}
}

View File

@ -253,6 +253,50 @@ class FortePaymentDriver extends BaseDriver
->first();
}
public function getLocation()
{
$response = $this->stubRequest()
->withQueryParameters(['page_size' => 10000])
->get("{$this->baseUri()}/organizations/{$this->getOrganisationId()}/locations/{$this->getLocationId()}");
if($response->successful())
return $response->json();
return false;
}
public function updateFees()
{
$response = $this->getLocation();
if($response)
{
$body = $response['services'];
$fees_and_limits = $this->company_gateway->fees_and_limits;
if($body['card']['service_fee_percentage'] > 0 || $body['card']['service_fee_additional_amount'] > 0){
$fees_and_limits->{1}->fee_amount = $body['card']['service_fee_additional_amount'];
$fees_and_limits->{1}->fee_percent = $body['card']['service_fee_percentage'];
}
if($body['debit']['service_fee_percentage'] > 0 || $body['debit']['service_fee_additional_amount'] > 0) {
$fees_and_limits->{2}->fee_amount = $body['debit']['service_fee_additional_amount'];
$fees_and_limits->{2}->fee_percent = $body['debit']['service_fee_percentage'];
}
$this->company_gateway->fees_and_limits = $fees_and_limits;
$this->company_gateway->save();
}
return false;
}
public function importCustomers()
{
@ -270,11 +314,12 @@ class FortePaymentDriver extends BaseDriver
$data = $factory->convertToNinja($customer, $this->company_gateway->company);
if(strlen($customer['email']) == 0 || $this->getClient($customer['email']))
if(strlen($data['email']) == 0 || $this->getClient($data['email']))
continue;
$client_repo->save($data, ClientFactory::create($this->company_gateway->company_id, $this->company_gateway->user_id));
//persist any payment methods here!
}
}

View File

@ -577,6 +577,11 @@ class PayPalPPCPPaymentDriver extends BaseDriver
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

@ -424,7 +424,7 @@ class PayPalRestPaymentDriver extends BaseDriver
SystemLog::EVENT_GATEWAY_FAILURE,
SystemLog::TYPE_PAYPAL,
$this->client,
$this->client->company,
$this->client->company ?? $this->company_gateway->company,
);
throw new PaymentFailed("Gateway failure - {$r->body()}", 401);
@ -474,4 +474,10 @@ class PayPalRestPaymentDriver extends BaseDriver
return false;
}
public function importCustomers()
{
return true;
}
}

View File

@ -59,6 +59,9 @@ class CreditCard
'enc_key' => $data['enc_key'],
'integrator_id' => $this->paytrace->company_gateway->getConfigField('integratorId'),
'billing_address' => $this->buildBillingAddress(),
'email' => $this->paytrace->client->present()->email(),
'phone' => $this->paytrace->client->present()->phone(),
];
$response = $this->paytrace->gatewayRequest('/v1/customer/pt_protect_create', $post_data);

View File

@ -11,19 +11,24 @@
namespace App\PaymentDrivers;
use App\Exceptions\SystemError;
use App\Http\Requests\Payments\PaymentWebhookRequest;
use App\Jobs\Util\SystemLogger;
use App\Models\ClientGatewayToken;
use App\Models\GatewayType;
use App\Models\Invoice;
use App\Models\Payment;
use App\Utils\CurlUtils;
use App\Models\SystemLog;
use App\Models\GatewayType;
use App\Models\PaymentHash;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\PayTrace\CreditCard;
use App\Utils\CurlUtils;
use App\Factory\ClientFactory;
use App\Exceptions\SystemError;
use App\Jobs\Util\SystemLogger;
use App\Utils\Traits\MakesHash;
use App\Models\ClientGatewayToken;
use App\Repositories\ClientRepository;
use App\PaymentDrivers\PayTrace\CreditCard;
use App\Repositories\ClientContactRepository;
use App\Http\Requests\Payments\PaymentWebhookRequest;
use App\Models\ClientContact;
use App\PaymentDrivers\Factory\PaytraceCustomerFactory;
class PaytracePaymentDriver extends BaseDriver
{
@ -260,4 +265,62 @@ class PaytracePaymentDriver extends BaseDriver
return false;
}
public function importCustomers()
{
$data = [
'integrator_id' => $this->company_gateway->getConfigField('integratorId'),
];
$response = $this->gatewayRequest('/v1/customer/export', $data);
nlog($response);
if ($response && $response->success) {
$client_repo = new ClientRepository(new ClientContactRepository());
$factory = new PaytraceCustomerFactory();
foreach($response->customers as $customer)
{
$data = $factory->convertToNinja($customer, $this->company_gateway->company);
$client = false;
if(str_contains($data['contacts'][0]['email'], "@"))
{
$client = ClientContact::query()
->where('company_id', $this->company_gateway->company_id)
->where('email', $data['contacts'][0]['email'])
->first()->client ?? false;
}
if(!$client)
$client = $client_repo->save($data, ClientFactory::create($this->company_gateway->company_id, $this->company_gateway->user_id));
$this->client = $client;
if(ClientGatewayToken::query()->where('client_id', $client->id)->where('token',$data['card']['token'])->exists())
continue;
$cgt = [];
$cgt['token'] = $data['card']['token'];
$cgt['payment_method_id'] = GatewayType::CREDIT_CARD;
$payment_meta = new \stdClass();
$payment_meta->exp_month = $data['card']['expiry_month'];
$payment_meta->exp_year = $data['card']['expiry_year'];
$payment_meta->brand = 'CC';
$payment_meta->last4 = $data['card']['last4'];
$payment_meta->type = GatewayType::CREDIT_CARD;
$cgt['payment_meta'] = $payment_meta;
$token = $this->storeGatewayToken($cgt, []);
}
}
}
}

View File

@ -197,7 +197,7 @@ class CreditCard implements MethodInterface
{
$square_card = new \Square\Models\Card();
$square_card->setCustomerId($this->findOrCreateClient());
$square_card->setCustomerId($this->square_driver->findOrCreateClient());
$body = new \Square\Models\CreateCardRequest(uniqid("st", true), $source_id, $square_card);
@ -238,82 +238,5 @@ class CreditCard implements MethodInterface
return false;
}
private function findOrCreateClient()
{
$email_address = new \Square\Models\CustomerTextFilter();
$email_address->setExact($this->square_driver->client->present()->email());
$filter = new \Square\Models\CustomerFilter();
$filter->setEmailAddress($email_address);
$query = new \Square\Models\CustomerQuery();
$query->setFilter($filter);
$body = new \Square\Models\SearchCustomersRequest();
$body->setQuery($query);
$api_response = $this->square_driver
->init()
->square
->getCustomersApi()
->searchCustomers($body);
$customers = false;
if ($api_response->isSuccess()) {
$customers = $api_response->getBody();
$customers = json_decode($customers);
if (count([$api_response->getBody(), 1]) == 0) {
$customers = false;
}
} else {
$errors = $api_response->getErrors();
}
if ($customers && property_exists($customers, 'customers')) {
return $customers->customers[0]->id;
}
return $this->createClient();
}
private function createClient()
{
$country = $this->square_driver->client->country ? $this->square_driver->client->country->iso_3166_2 : $this->square_driver->client->company->country()->iso_3166_2;
/* Step two - create the customer */
$billing_address = new \Square\Models\Address();
$billing_address->setAddressLine1($this->square_driver->client->address1);
$billing_address->setAddressLine2($this->square_driver->client->address2);
$billing_address->setLocality($this->square_driver->client->city);
$billing_address->setAdministrativeDistrictLevel1($this->square_driver->client->state);
$billing_address->setPostalCode($this->square_driver->client->postal_code);
$billing_address->setCountry($country);
$body = new \Square\Models\CreateCustomerRequest();
$body->setGivenName($this->square_driver->client->present()->name());
$body->setFamilyName('');
$body->setEmailAddress($this->square_driver->client->present()->email());
$body->setAddress($billing_address);
// $body->setPhoneNumber($this->square_driver->client->phone);
$body->setReferenceId($this->square_driver->client->number);
$body->setNote('Created by Invoice Ninja.');
$api_response = $this->square_driver
->init()
->square
->getCustomersApi()
->createCustomer($body);
if ($api_response->isSuccess()) {
$result = $api_response->getResult();
return $result->getCustomer()->getId();
} else {
$errors = $api_response->getErrors();
nlog($errors);
return $this->processUnsuccessfulPayment($api_response);
}
}
}

View File

@ -11,22 +11,27 @@
namespace App\PaymentDrivers;
use App\Http\Requests\Payments\PaymentWebhookRequest;
use App\Jobs\Util\SystemLogger;
use App\Models\ClientGatewayToken;
use App\Models\GatewayType;
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\Utils\Traits\MakesHash;
use Square\Utils\WebhooksHelper;
use App\Models\ClientGatewayToken;
use App\Repositories\ClientRepository;
use Square\Models\WebhookSubscription;
use App\PaymentDrivers\Square\CreditCard;
use App\PaymentDrivers\Square\SquareWebhook;
use App\Utils\Traits\MakesHash;
use Square\Models\Builders\RefundPaymentRequestBuilder;
use App\Repositories\ClientContactRepository;
use Square\Models\CreateWebhookSubscriptionRequest;
use Square\Models\WebhookSubscription;
use Square\Utils\WebhooksHelper;
use App\Http\Requests\Payments\PaymentWebhookRequest;
use App\PaymentDrivers\Factory\SquareCustomerFactory;
use Square\Models\Builders\RefundPaymentRequestBuilder;
class SquarePaymentDriver extends BaseDriver
{
@ -442,4 +447,191 @@ class SquarePaymentDriver extends BaseDriver
return (bool) count($api_response->getErrors()) == 0;
}
public function importCustomers()
{
$limit = 100;
$api_response = $this->init()
->square
->getCustomersApi()
->listCustomers(null,
$limit,
'DEFAULT',
'DESC'
);
if ($api_response->isSuccess()) {
while ($api_response->getResult()->getCustomers()) {
$customers = $api_response->getResult()->getCustomers();
$client_repo = new ClientRepository(new ClientContactRepository());
nlog($customers);
foreach($customers as $customer)
{
$data = (new SquareCustomerFactory())->convertToNinja($customer, $this->company_gateway->company);
$client = ClientContact::where('company_id', $this->company_gateway->company_id)->where('email', $customer->getEmailAddress())->first()->client ?? false;
if(!$client)
$client = $client_repo->save($data, ClientFactory::create($this->company_gateway->company_id, $this->company_gateway->user_id));
$this->client = $client;
foreach($data['cards'] as $card) {
if(ClientGatewayToken::where('company_id', $this->company_gateway->company_id)->where('token', $card['token'])->exists())
continue;
$this->storeGatewayToken($card);
}
}
$c = $api_response->getCursor();
if ($c) {
$api_response = $client->getCustomersApi()->listCustomers(
$c,
$limit,
'DEFAULT',
'DESC'
);
} else {
break;
}
}
}
}
private function findClient($email = null)
{
$email_address_string = $email ?? $this->client->present()->email();
$email_address = new \Square\Models\CustomerTextFilter();
$email_address->setExact($email_address_string);
$filter = new \Square\Models\CustomerFilter();
$filter->setEmailAddress($email_address);
$query = new \Square\Models\CustomerQuery();
$query->setFilter($filter);
$body = new \Square\Models\SearchCustomersRequest();
$body->setQuery($query);
$api_response = $this->init()
->square
->getCustomersApi()
->searchCustomers($body);
$customers = false;
if ($api_response->isSuccess()) {
$customers = $api_response->getBody();
$customers = json_decode($customers);
if (count([$api_response->getBody(), 1]) == 0) {
$customers = false;
}
} else {
$errors = $api_response->getErrors();
}
if ($customers && property_exists($customers, 'customers')) {
return $customers->customers[0]->id;
}
return false;
}
public function findOrCreateClient()
{
if($customer_id = $this->findClient())
return $customer_id;
return $this->createClient();
}
private function createClient()
{
$country = $this->client->country ? $this->client->country->iso_3166_2 : $this->client->company->country()->iso_3166_2;
/* Step two - create the customer */
$billing_address = new \Square\Models\Address();
$billing_address->setAddressLine1($this->client->address1);
$billing_address->setAddressLine2($this->client->address2);
$billing_address->setLocality($this->client->city);
$billing_address->setAdministrativeDistrictLevel1($this->client->state);
$billing_address->setPostalCode($this->client->postal_code);
$billing_address->setCountry($country);
$body = new \Square\Models\CreateCustomerRequest();
$body->setGivenName($this->client->present()->name());
$body->setFamilyName('');
$body->setEmailAddress($this->client->present()->email());
$body->setAddress($billing_address);
$body->setReferenceId($this->client->number);
$body->setNote('Created by Invoice Ninja.');
$api_response = $this->init()
->square
->getCustomersApi()
->createCustomer($body);
if ($api_response->isSuccess()) {
$result = $api_response->getResult();
return $result->getCustomer()->getId();
} else {
$errors = $api_response->getErrors();
nlog($errors);
$error = end($errors);
$data = [
'response' => $error->getDetail(),
'error' => $error->getDetail(),
'error_code' => $error->getCode(),
];
return $this->processUnsuccessfulTransaction($data);
}
}
}