diff --git a/app/DataProviders/CAProvinces.php b/app/DataProviders/CAProvinces.php new file mode 100644 index 000000000000..251f6e7c9262 --- /dev/null +++ b/app/DataProviders/CAProvinces.php @@ -0,0 +1,55 @@ + 'Alberta', + 'BC' => 'British Columbia', + 'MB' => 'Manitoba', + 'NB' => 'New Brunswick', + 'NL' => 'Newfoundland And Labrador', + 'NS' => 'Nova Scotia', + 'ON' => 'Ontario', + 'PE' => 'Prince Edward Island', + 'QC' => 'Quebec', + 'SK' => 'Saskatchewan', + 'NT' => 'Northwest Territories', + 'NU' => 'Nunavut', + 'YT' => 'Yukon' + ]; + + /** + * Get the name of the province or territory for a given abbreviation. + * + * @param string $abbreviation + * @return string + */ + public static function getName($abbreviation) { + return self::$provinces[$abbreviation]; + } + + /** + * Get all provinces and territories. + * + * @return array + */ + public static function get() { + return self::$provinces; + } + + /** + * Get the abbreviation for a given province or territory name. + * + * @param string $name + * @return string + */ + public static function getAbbreviation($name) { + return array_search(ucwords($name), self::$provinces); + } +} diff --git a/app/DataProviders/Frequencies.php b/app/DataProviders/Frequencies.php new file mode 100644 index 000000000000..503d40973dc4 --- /dev/null +++ b/app/DataProviders/Frequencies.php @@ -0,0 +1,19 @@ +client->contacts->firstWhere('is_primary', 1)->toArray())->merge([ + 'home_phone' =>$contact->client->phone, + 'custom_identifier' => $contact->client->number, + 'name' =>$contact->client->name, + 'id' => null + ] )->all(); + + $this->attributes = $this->newAttributeBag(Arr::only($contact, $this->fields) ); + } + + private $fields = [ + 'name', + 'email', + 'home_phone', + 'phone', + 'custom_identifier', + 'customer_type' , + 'id' + ]; + + private $defaults = [ + 'customer_type' => "Business", + 'customer_identifier' => null, + 'id' => null + ]; + + public function render() + { + return render('gateways.rotessa.components.contact', array_merge($this->defaults, $this->attributes->getAttributes() ) ); + } +} + +// Address Component +class AddressComponent extends Component +{ + private $fields = [ + 'address_1', + 'address_2', + 'city', + 'postal_code', + 'province_code', + 'country' + ]; + + private $defaults = [ + 'country' => 'US' + ]; + + public array $address; + + public function __construct(array $address) { + $this->address = $address; + if(strlen($this->address['state']) > 2 ) { + $this->address['state'] = $this->address['country'] == 'US' ? array_search($this->address['state'], USStates::$states) : CAProvinces::getAbbreviation($this->address['state']); + } + + $this->attributes = $this->newAttributeBag( + Arr::only(Arr::mapWithKeys($this->address, function ($item, $key) { + return in_array($key, ['address1','address2','state'])?[ (['address1'=>'address_1','address2'=>'address_2','state'=>'province_code'])[$key] => $item ] :[ $key => $item ]; + }), + $this->fields) ); + } + + + public function render() + { + return render('gateways.rotessa.components.address',array_merge( $this->defaults, $this->attributes->getAttributes() ) ); + } +} + +// AmericanBankInfo Component +class AccountComponent extends Component +{ + private $fields = [ + 'bank_account_type', + 'routing_number', + 'institution_number', + 'transit_number', + 'bank_name', + 'country', + 'account_number' + ]; + + private $defaults = [ + 'bank_account_type' => null, + 'routing_number' => null, + 'institution_number' => null, + 'transit_number' => null, + 'bank_name' => ' ', + 'account_number' => null, + 'country' => 'US', + "authorization_type" => 'Online' + ]; + + public array $account; + + public function __construct(array $account) { + $this->account = $account; + $this->attributes = $this->newAttributeBag(Arr::only($this->account, $this->fields) ); + } + + public function render() + { + return render('gateways.rotessa.components.account', array_merge($this->attributes->getAttributes(), $this->defaults) ); + } +} diff --git a/app/Http/ViewComposers/RotessaComposer.php b/app/Http/ViewComposers/RotessaComposer.php new file mode 100644 index 000000000000..493d955267b4 --- /dev/null +++ b/app/Http/ViewComposers/RotessaComposer.php @@ -0,0 +1,16 @@ +with('states', $states); +}); + +// CAProvinces View Composer +View::composer(['*.rotessa.components.address','*.rotessa.components.banks.CA.bank','*.rotessa.components.dropdowns.country.CA'], function ($view) { + $provinces = CAProvinces::get(); + $view->with('provinces', $provinces); +}); \ No newline at end of file diff --git a/app/Models/Gateway.php b/app/Models/Gateway.php index 5d8c20d7c439..1b259197c0f5 100644 --- a/app/Models/Gateway.php +++ b/app/Models/Gateway.php @@ -105,7 +105,9 @@ class Gateway extends StaticModel $link = 'https://www.forte.net/'; } elseif ($this->id == 62) { $link = 'https://docs.btcpayserver.org/InvoiceNinja/'; - } + } elseif ($this->id == 4002) { + $link = 'https://rotessa.com'; + } return $link; } @@ -224,6 +226,15 @@ class Gateway extends StaticModel return [ GatewayType::CRYPTO => ['refund' => true, 'token_billing' => false, 'webhooks' => ['confirmed', 'paid_out', 'failed', 'fulfilled']], ]; //BTCPay + case 4002: + return [ + GatewayType::BANK_TRANSFER => [ + 'refund' => false, + 'token_billing' => true, + 'webhooks' => [], + ], + GatewayType::ACSS => ['refund' => false, 'token_billing' => true, 'webhooks' => []] + ]; // Rotessa default: return []; } diff --git a/app/PaymentDrivers/Rotessa/PaymentMethod.php b/app/PaymentDrivers/Rotessa/PaymentMethod.php new file mode 100755 index 000000000000..b52c2423bf7e --- /dev/null +++ b/app/PaymentDrivers/Rotessa/PaymentMethod.php @@ -0,0 +1,215 @@ +rotessa = $rotessa; + $this->rotessa->init(); + } + + /** + * Show the authorization page for Rotessa. + * + * @param array $data + * @return \Illuminate\View\View + */ + public function authorizeView(array $data): View + { + $data['contact'] = collect($data['client']->contacts->firstWhere('is_primary', 1)->toArray())->merge([ + 'home_phone' => $data['client']->phone, + 'custom_identifier' => $data['client']->number, + 'name' => $data['client']->name, + 'id' => null + ] )->all(); + $data['gateway'] = $this->rotessa; + $data['gateway_type_id'] = $data['client']->country->iso_3166_2 == 'US' ? GatewayType::BANK_TRANSFER : ( $data['client']->country->iso_3166_2 == 'CA' ? GatewayType::ACSS : (int) request('method')); + $data['account'] = [ + 'routing_number' => $data['client']->routing_id, + 'country' => $data['client']->country->iso_3166_2 + ]; + $data['address'] = collect($data['client']->toArray())->merge(['country' => $data['client']->country->iso_3166_2 ])->all(); + + return render('gateways.rotessa.bank_transfer.authorize', $data ); + } + /** + * Handle the authorization page for Rotessa. + * + * @param Request $request + * @return RedirectResponse + */ + public function authorizeResponse(Request $request): RedirectResponse + { + try { + $request->validate([ + 'gateway_type_id' => ['required','integer'], + 'country' => ['required'], + 'name' => ['required'], + 'address_1' => ['required'], + 'address_2' => ['required'], + 'city' => ['required'], + 'email' => ['required','email:filter'], + 'province_code' => ['required','size:2','alpha'], + 'postal_code' => ['required'], + 'authorization_type' => ['required'], + 'account_number' => ['required'], + 'bank_name' => ['required'], + 'phone' => ['required'], + 'home_phone' => ['required'], + 'bank_account_type'=>['required_if:country,US'], + 'routing_number'=>['required_if:country,US'], + 'institution_number'=>['required_if:country,CA','numeric'], + 'transit_number'=>['required_if:country,CA','numeric'], + 'custom_identifier'=>['required_without:customer_id'], + 'customer_id'=>['required_without:custom_identifier','integer'], + ]); + $customer = new Customer( ['address' => $request->only('address_1','address_2','city','postal_code','province_code','country'), 'custom_identifier' => $request->input('custom_identifier') ] + $request->all()); + $this->rotessa->findOrCreateCustomer($customer->resolve()); + + return redirect()->route('client.payment_methods.index')->withMessage(ctrans('texts.payment_method_added')); + + } catch (\Throwable $e) { + return $this->rotessa->processInternallyFailedPayment($this->rotessa, new ClientPortalAuthorizationException( get_class( $e) . " : {$e->getMessage()}", (int) $e->getCode() )); + } + + return back()->withMessage(ctrans('texts.unable_to_verify_payment_method')); + } + + /** + * Payment view for the Rotessa. + * + * @param array $data + * @return \Illuminate\View\View + */ + public function paymentView(array $data): View + { + $data['gateway'] = $this->rotessa; + $data['amount'] = $data['total']['amount_with_fee']; + $data['due_date'] = date('Y-m-d', min(max(strtotime($data['invoices']->max('due_date')), strtotime('now')), strtotime('+1 day'))); + $data['process_date'] = $data['due_date']; + $data['currency'] = $this->rotessa->client->getCurrencyCode(); + $data['frequency'] = Frequencies::getOnePayment(); + $data['installments'] = 1; + $data['invoice_nums'] = $data['invoices']->pluck('invoice_number')->join(', '); + return render('gateways.rotessa.bank_transfer.pay', $data ); + } + + /** + * Handle payments page for Rotessa. + * + * @param PaymentResponseRequest $request + * @return void + */ + public function paymentResponse(PaymentResponseRequest $request) + { + $response= null; + $customer = null; + try { + $request->validate([ + 'source' => ['required','string','exists:client_gateway_tokens,token'], + 'amount' => ['required','numeric'], + 'token_id' => ['required','integer','exists:client_gateway_tokens,id'], + 'process_date'=> ['required','date','after_or_equal:today'], + ]); + $customer = ClientGatewayToken::query() + ->where('company_gateway_id', $this->rotessa->company_gateway->id) + ->where('client_id', $this->rotessa->client->id) + ->where('id', (int) $request->input('token_id')) + ->where('token', $request->input('source')) + ->first(); + if(!$customer) throw new \Exception('Client gateway token not found!', 605); + + $transaction = new Transaction($request->only('frequency' ,'installments','amount','process_date','comment')); + $transaction->additional(['customer_id' => $customer->gateway_customer_reference]); + $transaction = array_filter( $transaction->resolve()); + $response = $this->rotessa->gateway->capture($transaction)->send(); + if(!$response->isSuccessful()) throw new \Exception($response->getMessage(), (int) $response->getCode()); + + return $this->processPendingPayment($response->getParameter('id'), (float) $response->getParameter('amount'), (int) $customer->gateway_type_id , $customer->token); + } catch(\Throwable $e) { + $this->processUnsuccessfulPayment( new InvalidResponseException($e->getMessage(), (int) $e->getCode()) ); + } + } + + public function processPendingPayment($payment_id, float $amount, int $gateway_type_id, $payment_method ) + { + $data = [ + 'payment_method' => $payment_method, + 'payment_type' => $gateway_type_id, + 'amount' => $amount, + 'transaction_reference' =>$payment_id, + 'gateway_type_id' => $gateway_type_id, + ]; + $payment = $this->rotessa->createPayment($data, Payment::STATUS_PENDING); + SystemLogger::dispatch( + [ 'data' => $data ], + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_SUCCESS, + 880, + $this->rotessa->client, + $this->rotessa->client->company, + ); + + return redirect()->route('client.payments.show', [ 'payment' => $this->rotessa->encodePrimaryKey($payment->id) ]); + } + + /** + * Handle unsuccessful payment for Rotessa. + * + * @param Exception $exception + * @throws PaymentFailed + * @return void + */ + public function processUnsuccessfulPayment(\Exception $exception): void + { + $this->rotessa->sendFailureMail($exception->getMessage()); + + SystemLogger::dispatch( + $exception->getMessage(), + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_FAILURE, + 880, + $this->rotessa->client, + $this->rotessa->client->company, + ); + + throw new PaymentFailed($exception->getMessage(), $exception->getCode()); + } +} diff --git a/app/PaymentDrivers/Rotessa/Resources/Customer.php b/app/PaymentDrivers/Rotessa/Resources/Customer.php new file mode 100644 index 000000000000..c2514dfdd8c1 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/Resources/Customer.php @@ -0,0 +1,22 @@ +resource->jsonSerialize(); + } + + function toArray(Request $request) : array { + return $this->additional + parent::toArray($request); + } +} diff --git a/app/PaymentDrivers/Rotessa/Resources/Transaction.php b/app/PaymentDrivers/Rotessa/Resources/Transaction.php new file mode 100644 index 000000000000..84ce332860f8 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/Resources/Transaction.php @@ -0,0 +1,23 @@ +resource->jsonSerialize(); + } + + function toArray(Request $request) : array { + return $this->additional + parent::toArray($request); + } +} diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/AbstractClient.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/AbstractClient.php new file mode 100644 index 000000000000..c84a97322717 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/AbstractClient.php @@ -0,0 +1,21 @@ +default_parameters; + } + + public function setDefaultParameters(array $params) { + $this->default_parameters = $params; + } + +} diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/ApiTrait.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/ApiTrait.php new file mode 100644 index 000000000000..5fc947713f3a --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/ApiTrait.php @@ -0,0 +1,41 @@ +createRequest('GetCustomers', [] ); + } + public function postCustomers(array $params) : RequestInterface { + return $this->createRequest('PostCustomers', $params ); + } + public function getCustomersId(array $params) : RequestInterface { + return $this->createRequest('GetCustomersId', $params ); + } + public function patchCustomersId(array $params) : RequestInterface { + return $this->createRequest('PatchCustomersId', $params ); + } + public function postCustomersShowWithCustomIdentifier(array $params) : RequestInterface { + return $this->createRequest('PostCustomersShowWithCustomIdentifier', $params ); + } + public function getTransactionSchedulesId(array $params) : RequestInterface { + return $this->createRequest('GetTransactionSchedulesId', $params ); + } + public function deleteTransactionSchedulesId(array $params) : RequestInterface { + return $this->createRequest('DeleteTransactionSchedulesId', $params ); + } + public function patchTransactionSchedulesId(array $params) : RequestInterface { + return $this->createRequest('PatchTransactionSchedulesId', $params ); + } + public function postTransactionSchedules(array $params) : RequestInterface { + return $this->createRequest('PostTransactionSchedules', $params ); + } + public function postTransactionSchedulesCreateWithCustomIdentifier(array $params) : RequestInterface { + return $this->createRequest('PostTransactionSchedulesCreateWithCustomIdentifier', $params ); + } + public function postTransactionSchedulesUpdateViaPost(array $params) : RequestInterface { + return $this->createRequest('PostTransactionSchedulesUpdateViaPost', $params ); + } + } diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/ClientInterface.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/ClientInterface.php new file mode 100644 index 000000000000..4d08fb0441f2 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/ClientInterface.php @@ -0,0 +1,11 @@ + 1234567890 ]; + + protected $test_mode = true; + + protected $api_key; + + public function getName() + { + return 'Rotessa'; + } + + public function getDefaultParameters() : array + { + return array_merge($this->default_parameters, array('api_key' => $this->api_key, 'test_mode' => $this->test_mode ) ); + } + + public function setTestMode($value) { + $this->test_mode = $value; + } + + public function getTestMode() { + return $this->test_mode; + } + + protected function createRequest($class_name, ?array $parameters = [] ) :RequestInterface { + $class = null; + $class_name = "Omnipay\\Rotessa\\Message\\Request\\$class_name"; + $parameters = $class_name::hasModel() ? (($parameters = ($class_name::getModel($parameters)))->validate() ? $parameters->jsonSerialize() : null ) : $parameters; + try { + $class = new $class_name($this->httpClient, $this->httpRequest, $this->getDefaultParameters() + $parameters ); + } catch (\Throwable $th) { + throw $th; + } + + return $class; + } + + function setApiKey($value) { + $this->api_key = $value; + } + + function getApiKey() { + return $this->api_key; + } + + function authorize(array $options = []) : RequestInterface { + return $this->postCustomers($options); + } + + function capture(array $options = []) : RequestInterface { + return array_key_exists('customer_id', $options)? $this->postTransactionSchedules($options) : $this->postTransactionSchedulesCreateWithCustomIdentifier($options) ; + } + + function updateCustomer(array $options) : RequestInterface { + return $this->patchCustomersId($options); + } + + function fetchTransaction($id = null) : RequestInterface { + return $this->getTransactionSchedulesId(compact('id')); + } + +} \ No newline at end of file diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Http/Client.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Http/Client.php new file mode 100644 index 000000000000..4c8ea0d29075 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Http/Client.php @@ -0,0 +1,82 @@ +httpClient = $httpClient ?: HttpClientDiscovery::find(); + $this->requestFactory = $requestFactory ?: MessageFactoryDiscovery::find(); + parent::__construct($httpClient, $requestFactory); + } + + /** + * @param $method + * @param $uri + * @param array $headers + * @param string|array|resource|StreamInterface|null $body + * @param string $protocolVersion + * @return ResponseInterface + * @throws \Http\Client\Exception + */ + public function request( + $method, + $uri, + array $headers = [], + $body = null, + $protocolVersion = '1.1' + ) { + return $this->sendRequest($method, $uri, $headers, $body, $protocolVersion); + + } + + /** + * @param RequestInterface $request + * @return ResponseInterface + * @throws \Http\Client\Exception + */ + private function sendRequest( $method, + $uri, + array $headers = [], + $body = null, + $protocolVersion = '1.1') + { + + $response = null; + + try { + if( method_exists($this->httpClient, 'sendRequest')) + $response = $this->httpClient->sendRequest( $this->requestFactory->createRequest($method, $uri, $headers, $body, $protocolVersion)); + else $response = $this->httpClient->request($method, $uri, compact('body','headers')); + } catch (\Http\Client\Exception\NetworkException $networkException) { + throw new NetworkException($networkException->getMessage(), $request, $networkException); + } catch (\Exception $exception) { + throw new RequestException($exception->getMessage(), $request, $exception); + } + + return $response; + } +} \ No newline at end of file diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Http/Response/Response.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Http/Response/Response.php new file mode 100644 index 000000000000..8d665ac8546e --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Http/Response/Response.php @@ -0,0 +1,32 @@ +content, true) )) { + $data = $data['errors'][0]; + $this->reason_phrase = $data['error_message'] ; + $this->reason_code = $data['error_message'] ; + } + } + + public function getReasonPhrase() { + return $this->reason_phrase; + } + + public function getReasonCode() { + return $this->reason_code; + } +} diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/IsValidTypeTrait.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/IsValidTypeTrait.php new file mode 100644 index 000000000000..266ba3036d9d --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/IsValidTypeTrait.php @@ -0,0 +1,12 @@ +api_key = $value; + } + + public function getData() { + try { + if(empty($this->api_key)) throw new \Exception('No Api Key Found!'); + $this->validate( ...array_keys($data = $this->getParameters())); + } catch (\Throwable $th) { + throw new \Omnipay\Rotessa\Exception\ValidationException($th->getMessage() , 600, $th); + } + + return (array) $data; + } + + abstract public function sendData($data) : ResponseInterface; + + abstract protected function sendRequest(string $method, string $endpoint, array $headers = [], array $data = [] ); + + abstract protected function createResponse(array $data) : ResponseInterface; + + abstract public function getEndpointUrl(): string; + + public function getEndpoint() : string { + return $this->endpoint; + } + + public function getTestMode() { + return $this->test_mode; + } + + public function setTestMode($mode) { + $this->test_mode = $mode; + } + } \ No newline at end of file diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/BaseRequest.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/BaseRequest.php new file mode 100644 index 000000000000..4b68cf0aa2ff --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/BaseRequest.php @@ -0,0 +1,93 @@ +initialize($model); + } + + protected function sendRequest(string $method, string $endpoint, array $headers = [], array $data = []) + { + /** + * @param $method + * @param $uri + * @param array $headers + * @param string|resource|StreamInterface|null $body + * @param string $protocolVersion + * @return ResponseInterface + * @throws \Http\Client\Exception + */ + $response = $this->httpClient->request($method, $endpoint, $headers, json_encode($data) ) ; + $this->response = new Response ($response->getBody()->getContents(), $response->getStatusCode(), $response->getHeaders(), true); + } + + + protected function createResponse(array $data): ResponseInterface { + + return new BaseResponse($this, $data, $this->response->getStatusCode(), $this->response->getReasonPhrase()); + } + + protected function replacePlaceholder($string, $array) { + $pattern = "/\{([^}]+)\}/"; + $replacement = function($matches) use($array) { + $key = $matches[1]; + if (array_key_exists($key, $array)) { + return $array[$key]; + } else { + return $matches[0]; + } + }; + + return preg_replace_callback($pattern, $replacement, $string); + } + + public function sendData($data) :ResponseInterface { + $headers = [ + 'Content-Type' => 'application/json', + 'Accept' => 'application/json', + 'Authorization' => "Token token={$this->api_key}" + ]; + + $this->sendRequest( + $this->method, + $this->getEndpointUrl(), + $headers, + $data); + + return $this->createResponse(json_decode($this->response->getContent(), true)); + } + + public function getEndpoint() : string { + return $this->replacePlaceholder($this->endpoint, $this->getParameters()); + } + + public function getEndpointUrl() : string { + return sprintf('https://%s.%s/v%d%s',$this->test_mode ? self::ENVIRONMENT_SANDBOX : self::ENVIRONMENT_LIVE ,$this->base_url, $this->api_version, $this->getEndpoint()); + } + + public static function hasModel() : bool { + return (bool) static::$model; + } + + public static function getModel($parameters = []) { + $class_name = static::$model; + $class_name = "Omnipay\\Rotessa\\Model\\{$class_name}Model"; + return new $class_name($parameters); + } +} \ No newline at end of file diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/DeleteTransactionSchedulesId.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/DeleteTransactionSchedulesId.php new file mode 100644 index 000000000000..7c03c42b0dc6 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/DeleteTransactionSchedulesId.php @@ -0,0 +1,18 @@ +setParameter('id',$value); + } + +} diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/GetCustomers.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/GetCustomers.php new file mode 100644 index 000000000000..17ffde5355d9 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/GetCustomers.php @@ -0,0 +1,14 @@ +setParameter('id',$value); + } +} diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/GetTransactionSchedulesId.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/GetTransactionSchedulesId.php new file mode 100644 index 000000000000..47578d06eb8b --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/GetTransactionSchedulesId.php @@ -0,0 +1,17 @@ +setParameter('id',$value); + } + } diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PatchCustomersId.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PatchCustomersId.php new file mode 100644 index 000000000000..092e378b9fd5 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PatchCustomersId.php @@ -0,0 +1,65 @@ +setParameter('id',$value); + } + public function setCustomIdentifier(string $value) { + $this->setParameter('custom_identifier',$value); + } + public function setName(string $value) { + $this->setParameter('name',$value); + } + public function setEmail(string $value) { + $this->setParameter('email',$value); + } + public function setCustomerType(string $value) { + $this->setParameter('customer_type',$value); + } + public function setHomePhone(string $value) { + $this->setParameter('home_phone',$value); + } + public function setPhone(string $value) { + $this->setParameter('phone',$value); + } + public function setBankName(string $value) { + $this->setParameter('bank_name',$value); + } + public function setInstitutionNumber(string $value) { + $this->setParameter('institution_number',$value); + } + public function setTransitNumber(string $value) { + $this->setParameter('transit_number',$value); + } + public function setBankAccountType(string $value) { + $this->setParameter('bank_account_type',$value); + } + public function setAuthorizationType(string $value) { + $this->setParameter('authorization_type',$value); + } + public function setRoutingNumber(string $value) { + $this->setParameter('routing_number',$value); + } + public function setAccountNumber(string $value) { + $this->setParameter('account_number',$value); + } + public function setAddress(array $value) { + $this->setParameter('address',$value); + } + public function setTransactionSchedules(array $value) { + $this->setParameter('transaction_schedules',$value); + } + public function setFinancialTransactions(array $value) { + $this->setParameter('financial_transactions',$value); + } + } diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PatchTransactionSchedulesId.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PatchTransactionSchedulesId.php new file mode 100644 index 000000000000..fa04b9f05da6 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PatchTransactionSchedulesId.php @@ -0,0 +1,22 @@ +setParameter('id',$value); + } + public function setAmount(int $value) { + $this->setParameter('amount',$value); + } + public function setComment(string $value) { + $this->setParameter('comment',$value); + } + } diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PostCustomers.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PostCustomers.php new file mode 100644 index 000000000000..a0c54fe65ca9 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PostCustomers.php @@ -0,0 +1,60 @@ +setParameter('id',$value); + } + public function setCustomIdentifier(string $value) { + $this->setParameter('custom_identifier',$value); + } + public function setName(string $value) { + $this->setParameter('name',$value); + } + public function setEmail(string $value) { + $this->setParameter('email',$value); + } + public function setCustomerType(string $value) { + $this->setParameter('customer_type',$value); + } + public function setHomePhone(string $value) { + $this->setParameter('home_phone',$value); + } + public function setPhone(string $value) { + $this->setParameter('phone',$value); + } + public function setBankName(string $value) { + $this->setParameter('bank_name',$value); + } + public function setInstitutionNumber(string $value = '') { + $this->setParameter('institution_number',$value); + } + public function setTransitNumber(string $value = '') { + $this->setParameter('transit_number',$value); + } + public function setBankAccountType(string $value) { + $this->setParameter('bank_account_type',$value); + } + public function setAuthorizationType(string $value = '') { + $this->setParameter('authorization_type',$value); + } + public function setRoutingNumber(string $value = '') { + $this->setParameter('routing_number',$value); + } + public function setAccountNumber(string $value) { + $this->setParameter('account_number',$value); + } + public function setAddress(array $value) { + $this->setParameter('address',$value); + } + } diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PostCustomersShowWithCustomIdentifier.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PostCustomersShowWithCustomIdentifier.php new file mode 100644 index 000000000000..d590cb618526 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PostCustomersShowWithCustomIdentifier.php @@ -0,0 +1,19 @@ +setParameter('custom_identifier',$value); + } + +} diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PostTransactionSchedules.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PostTransactionSchedules.php new file mode 100644 index 000000000000..80e28a7f5083 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PostTransactionSchedules.php @@ -0,0 +1,31 @@ +setParameter('customer_id',$value); + } + public function setProcessDate(string $value) { + $this->setParameter('process_date',$value); + } + public function setFrequency(string $value) { + $this->setParameter('frequency',$value); + } + public function setInstallments(int $value) { + $this->setParameter('installments',$value); + } + public function setComment(string $value) { + $this->setParameter('comment',$value); + } + } diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PostTransactionSchedulesCreateWithCustomIdentifier.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PostTransactionSchedulesCreateWithCustomIdentifier.php new file mode 100644 index 000000000000..fd5111dc9a74 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PostTransactionSchedulesCreateWithCustomIdentifier.php @@ -0,0 +1,16 @@ +setParameter('custom_identifier',$value); + } + +} diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PostTransactionSchedulesUpdateViaPost.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PostTransactionSchedulesUpdateViaPost.php new file mode 100644 index 000000000000..e037c5b4d322 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/PostTransactionSchedulesUpdateViaPost.php @@ -0,0 +1,24 @@ +setParameter('id',$value); + } + public function setAmount(int $value) { + $this->setParameter('amount',$value); + } + public function setComment(string $value) { + $this->setParameter('comment',$value); + } + } diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/RequestInterface.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/RequestInterface.php new file mode 100644 index 000000000000..cfbcf0095b24 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Request/RequestInterface.php @@ -0,0 +1,10 @@ +code = $code; + $this->message = $message; + } + + public function getData() { + return $this->getParameters(); + } + + public function getCode() { + return (int) $this->code; + } + + public function isSuccessful() { + return $this->code < 300; + } + + public function getMessage() { + return $this->message; + } + + protected function getParameters() { + return $this->data; + } + + public function getParameter(string $key) { + return $this->getParameters()[$key]; + } +} \ No newline at end of file diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Response/ResponseInterface.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Response/ResponseInterface.php new file mode 100644 index 000000000000..080eaab504b1 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Message/Response/ResponseInterface.php @@ -0,0 +1,9 @@ +required), array_filter($this->getParameters()) ); + if(!empty($required)) throw new ValidationException("Could not validate " . implode(",", array_keys($required)) ); + + return true; + } + + public function __get($key) { + return array_key_exists($key, $this->attributes) ? $this->getParameter($key) : null; + } + + public function __set($key, $value) { + if(array_key_exists($key, $this->attributes)) $this->setParameter($key, $value); + } + + public function __toString() : string { + return json_encode($this); + } + + public function toString() : string { + return $this->__toString(); + } + + public function __toArray() : array { + return $this->getParameters(); + } + + + public function toArray() : array { + return $this->__toArray(); + } + + public function initialize(array $params = []) { + $this->parameters = new ParameterBag; + $parameters = array_merge($this->defaults, $params); + if ($parameters) { + foreach ($this->attributes as $param => $type) { + $value = @$parameters[$param]; + if($value){ + settype($value, $type); + $this->setParameter($param, $value); + } + } + } + + return $this; + } +} diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Model/BaseModel.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Model/BaseModel.php new file mode 100644 index 000000000000..8064662068c4 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Model/BaseModel.php @@ -0,0 +1,24 @@ + "string" + ]; + protected $required = ['id']; + protected $defaults = ['id' => 0 ]; + + public function __construct($parameters = array()) { + $this->initialize($parameters); + } + + public function jsonSerialize() : array { + return array_intersect_key($this->toArray(), array_flip($this->required) ); + } +} diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Model/CustomerModel.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Model/CustomerModel.php new file mode 100644 index 000000000000..0fd67aea9441 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Model/CustomerModel.php @@ -0,0 +1,94 @@ + "string", + "custom_identifier" => "string", + "name" => "string", + "email" => "string", + "customer_type" => "string", + "home_phone" => "string", + "phone" => "string", + "bank_name" => "string", + "institution_number" => "string", + "transit_number" => "string", + "bank_account_type" => "string", + "authorization_type" => "string", + "routing_number" => "string", + "account_number" => "string", + "address" => "object", + "transaction_schedules" => "array", + "financial_transactions" => "array", + "active" => "bool" + ]; + + protected $defaults = ["active" => false,"customer_type" =>'Business',"bank_account_type" =>'Savings',"authorization_type" =>'Online',]; + protected $required = ["name","email","customer_type","home_phone","phone","bank_name","institution_number","transit_number","bank_account_type","authorization_type","routing_number","account_number","address",'custom_identifier']; + + public function validate() : bool { + try { + $country = $this->address->country; + if(!self::isValidCountry($country)) throw new \Exception("Invalid country!"); + + $this->required = array_diff($this->required, Country::isAmerican($country) ? ["institution_number", "transit_number"] : ["bank_account_type", "routing_number"]); + parent::validate(); + if(Country::isCanadian($country) ) { + if(!self::isValidTransitNumber($this->getParameter('transit_number'))) throw new \Exception("Invalid transit number!"); + if(!self::isValidInstitutionNumber($this->getParameter('institution_number'))) throw new \Exception("Invalid institution number!"); + } + if(!self::isValidCustomerType($this->getParameter('customer_type'))) throw new \Exception("Invalid customer type!"); + if(!self::isValidBankAccountType($this->getParameter('bank_account_type'))) throw new \Exception("Invalid bank account type!"); + if(!self::isValidAuthorizationType($this->getParameter('authorization_type'))) throw new \Exception("Invalid authorization type!"); + } catch (\Throwable $th) { + throw new ValidationException($th->getMessage()); + } + + return true; + } + + public static function isValidCountry(string $country ) : bool { + return Country::isValidCountryCode($country) || Country::isValidCountryName($country); + } + + public static function isValidTransitNumber(string $value ) : bool { + return strlen($value) == 5; + } + + public static function isValidInstitutionNumber(string $value ) : bool { + return strlen($value) == 3; + } + + public static function isValidCustomerType(string $value ) : bool { + return CustomerType::isValid($value); + } + + public static function isValidBankAccountType(string $value ) : bool { + return BankAccountType::isValid($value); + } + + public static function isValidAuthorizationType(string $value ) : bool { + return AuthorizationType::isValid($value); + } + + public function toArray() : array { + return [ 'address' => (array) $this->getParameter('address') ] + parent::toArray(); + } + + public function jsonSerialize() : array { + $address = (array) $this->getParameter('address'); + unset($address['country']); + + return compact('address') + parent::jsonSerialize(); + } +} diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Model/CustomerPatchModel.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Model/CustomerPatchModel.php new file mode 100644 index 000000000000..c2e51d50b135 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Model/CustomerPatchModel.php @@ -0,0 +1,16 @@ + "string", + "amount" => "float", + "comment" => "string", + "created_at" => "date", + "financial_transactions" => "array", + "frequency" => "string", + "installments" => "integer", + "next_process_date" => "date", + "process_date" => "date", + "updated_at" => "date", + "customer_id" => "string", + "custom_identifier" => "string", + ]; + + public const DATE_FORMAT = 'F j, Y'; + + protected $defaults = ["amount" =>0.00,"comment" =>' ',"financial_transactions" =>0,"frequency" =>'Once',"installments" =>1]; + + protected $required = ["amount","comment","frequency","installments","process_date"]; + + public function validate() : bool { + try { + parent::validate(); + if(!self::isValidDate($this->process_date)) throw new \Exception("Could not validate date "); + if(!self::isValidFrequency($this->frequency)) throw new \Exception("Invalid frequency"); + if(is_null($this->customer_id) && is_null($this->custom_identifier)) throw new \Exception("customer id or custom identifier is invalid"); + } catch (\Throwable $th) { + throw new ValidationException($th->getMessage()); + } + + return true; + } + + public function jsonSerialize() : array { + return ['customer_id' => $this->getParameter('customer_id'), 'custom_identifier' => $this->getParameter('custom_identifier') ] + parent::jsonSerialize() ; + } + + public function __toArray() : array { + return parent::__toArray() ; + } + + public function initialize(array $params = [] ) { + $o_params = array_intersect_key( + $params = array_intersect_key($params, $this->attributes), + ($attr = array_filter($this->attributes, fn($p) => $p != "date")) + ); + parent::initialize($o_params); + $d_params = array_diff_key($params, $attr); + array_walk($d_params, function($v,$k) { + $this->setParameter($k, self::formatDate( $v) ); + }, ); + + return $this; + } + + public static function isValidDate($date) : bool { + $d = DateTime::createFromFormat(self::DATE_FORMAT, $date); + // Check if the date is valid and matches the format + return $d && $d->format(self::DATE_FORMAT) === $date; + } + + public static function isValidFrequency($value) : bool { + return Frequency::isValid($value); + } + + protected static function formatDate($date) : string { + $d = new DateTime($date); + return $d->format(self::DATE_FORMAT); + } +} diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Model/TransactionSchedulesIdBodyModel.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Model/TransactionSchedulesIdBodyModel.php new file mode 100644 index 000000000000..119ac03999cb --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Model/TransactionSchedulesIdBodyModel.php @@ -0,0 +1,23 @@ + "int", + "comment" => "string", + ]; + + public const DATE_FORMAT = 'Y-m-d H:i:s'; + + private $_is_error = false; + + protected $defaults = ["amount" =>0,"comment" =>'0',]; + + protected $required = ["amount","comment",]; +} diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Model/TransactionSchedulesUpdateViaPostBodyModel.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Model/TransactionSchedulesUpdateViaPostBodyModel.php new file mode 100644 index 000000000000..749ae2f6b967 --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Model/TransactionSchedulesUpdateViaPostBodyModel.php @@ -0,0 +1,24 @@ + "int", + "amount" => "int", + "comment" => "string", + ]; + + public const DATE_FORMAT = 'Y-m-d H:i:s'; + + private $_is_error = false; + + protected $defaults = ["amount" =>0,"comment" =>'0',]; + + protected $required = ["amount","comment",]; +} diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Object/Address.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Object/Address.php new file mode 100644 index 000000000000..1c5952b112ef --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Object/Address.php @@ -0,0 +1,53 @@ + "string", + "address_2" => "string", + "city" => "string", + "id" => "int", + "postal_code" => "string", + "province_code" => "string", + "country" => "string" + ]; + + protected $required = ["address_1","address_2","city","postal_code","province_code",]; + + public function jsonSerialize() { + return array_intersect_key($this->getParameters(), array_flip($this->required)); + } + + public function getCountry() : string { + return $this->getParameter('country'); + } + + public function initialize(array $parameters) { + foreach($this->attributes as $param => $type) { + $value = @$parameters[$param] ; + settype($value, $type); + $value = $value ?? null; + $this->parameters->set($param, $value); + } + } + + public function __toArray() : array { + return $this->getParameters(); + } + + public function __toString() : string { + return $this->getFullAddress(); + } + + public function getFullAddress() :string { + $full_address = $this->getParameters(); + extract($full_address); + + return "$address_1 $address_2, $city, $postal_code $province_code, $country"; + } +} diff --git a/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Object/AuthorizationType.php b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Object/AuthorizationType.php new file mode 100644 index 000000000000..39dcebfa342f --- /dev/null +++ b/app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/Object/AuthorizationType.php @@ -0,0 +1,28 @@ + BankTransfer::class, + //GatewayType::BACS => Bacs::class, + GatewayType::ACSS => Acss::class, + // GatewayType::DIRECT_DEBIT => DirectDebit::class + ]; + + public function init(): self + { + + $this->gateway = Omnipay::create( + $this->company_gateway->gateway->provider + ); + $this->gateway->initialize((array) $this->company_gateway->getConfig()); + return $this; + } + + public function gatewayTypes(): array + { + $types = []; + + if ($this->client + && $this->client->currency() + && in_array($this->client->currency()->code, ['USD']) + && isset($this->client->country) + && in_array($this->client->country->iso_3166_2, ['US'])) { + $types[] = GatewayType::BANK_TRANSFER; + } + + if ($this->client + && $this->client->currency() + && in_array($this->client->currency()->code, ['CAD']) + && isset($this->client->country) + && in_array($this->client->country->iso_3166_2, ['CA'])) { + $types[] = GatewayType::ACSS; + } + + return $types; + } + + + public function setPaymentMethod($payment_method_id) + { + $class = self::$methods[$payment_method_id]; + $this->payment_method = new $class($this); + + return $this; + } + + public function authorizeView(array $data) + { + return $this->payment_method->authorizeView($data); + } + + public function authorizeResponse($request) + { + return $this->payment_method->authorizeResponse($request); + } + + public function processPaymentView(array $data) + { + return $this->payment_method->paymentView($data); + } + + public function processPaymentResponse($request) + { + return $this->payment_method->paymentResponse($request); + } + + public function importCustomers() { + $this->init(); + try { + $result = $this->gateway->getCustomers()->send(); + if(!$result->isSuccessful()) throw new \Exception($result->getMessage(), (int) $result->getCode()); + + $customers = collect($result->getData())->unique('email'); + $client_emails = $customers->pluck('email')->all(); + $company_id = $this->company_gateway->company->id; + $client_contacts = ClientContact::where('company_id', $company_id)->whereIn('email', $client_emails )->whereNull('deleted_at')->get(); + $client_contacts = $client_contacts->map(function($item, $key) use ($customers) { + return array_merge([], (array) $customers->firstWhere("email", $item->email) , ['custom_identifier' => $item->client->number, 'identifier' => $item->client->number ]); + } ); + + $client_contacts->each( + function($contact) use ($customers) { + sleep(10); + $result = $this->gateway->getCustomersId(['id' => ($contact = (object) $contact)->id])->send(); + $this->client = Client::find($contact->custom_identifier); + $customer = (new Customer($result->getData()))->additional(['id' => $contact->id, 'custom_identifier' => $contact->custom_identifier ] ); + $this->findOrCreateCustomer($customer->additional + $customer->jsonSerialize()); + } + ); + + } catch (\Throwable $th) { + $data = [ + 'transaction_reference' => null, + 'transaction_response' => $th->getMessage(), + 'success' => false, + 'description' => $th->getMessage(), + 'code' =>(int) $th->getCode() + ]; + + SystemLogger::dispatch(['server_response' => $th->getMessage(), 'data' => $data], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, 880 , $this->client , $this->company_gateway->company); + + + throw $th; + } + + return true; + } + + public function findOrCreateCustomer(array $data) + { + $result = null; + try { + + $existing = ClientGatewayToken::query() + ->where('company_gateway_id', $this->company_gateway->id) + ->where('client_id', $this->client->id) + ->orWhere(function (Builder $query) use ($data) { + $query->where('token', encrypt(join(".", Arr::only($data, 'id','custom_identifier'))) ) + ->where('gateway_customer_reference', Arr::only($data,'id')); + }) + ->exists(); + if ($existing) return true; + else if(!Arr::has($data,'id')) { + $result = $this->gateway->authorize($data)->send(); + if (!$result->isSuccessful()) throw new \Exception($result->getMessage(), (int) $result->getCode()); + + $customer = new Customer($result->getData()); + $data = array_filter($customer->resolve()); + } + + $payment_method_id = Arr::has($data,'address.postal_code') && ((int) $data['address']['postal_code'])? GatewayType::BANK_TRANSFER: GatewayType::ACSS; + $gateway_token = $this->storeGatewayToken( [ + 'payment_meta' => $data + ['brand' => 'Rotessa'], + 'token' => encrypt(join(".", Arr::only($data, 'id','custom_identifier'))), + 'payment_method_id' => $payment_method_id , + ], ['gateway_customer_reference' => + $data['id'] + , 'routing_number' => Arr::has($data,'routing_number') ? $data['routing_number'] : $data['transit_number'] ]); + + return $data['id']; + + throw new \Exception($result->getMessage(), (int) $result->getCode()); + + } catch (\Throwable $th) { + $data = [ + 'transaction_reference' => null, + 'transaction_response' => $th->getMessage(), + 'success' => false, + 'description' => $th->getMessage(), + 'code' =>(int) $th->getCode() + ]; + + SystemLogger::dispatch(['server_response' => is_null($result) ? '' : $result->getData(), 'data' => $data], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, 880 , $this->client, $this->client->company); + + throw $th; + } + } +} diff --git a/app/Providers/ComposerServiceProvider.php b/app/Providers/ComposerServiceProvider.php index d548a3d997ce..300d88f87768 100644 --- a/app/Providers/ComposerServiceProvider.php +++ b/app/Providers/ComposerServiceProvider.php @@ -13,6 +13,7 @@ namespace App\Providers; use App\Http\ViewComposers\PortalComposer; use Illuminate\Support\ServiceProvider; +use Illuminate\Support\Facades\Blade; class ComposerServiceProvider extends ServiceProvider { @@ -24,6 +25,9 @@ class ComposerServiceProvider extends ServiceProvider public function boot() { view()->composer('portal.*', PortalComposer::class); + include_once app_path('Http/ViewComposers/RotessaComposer.php'); + include_once app_path("Http/ViewComposers/Components/RotessaComponents.php"); + Blade::componentNamespace('App\\Http\\ViewComposers\\Components', 'rotessa'); } /** @@ -34,5 +38,6 @@ class ComposerServiceProvider extends ServiceProvider public function register() { // + } } diff --git a/app/Providers/RotessaServiceProvider.php b/app/Providers/RotessaServiceProvider.php new file mode 100644 index 000000000000..4f01a045dbf3 --- /dev/null +++ b/app/Providers/RotessaServiceProvider.php @@ -0,0 +1,31 @@ +registerComponent(); + } + + /** + * Register views. + */ + public function registerComponent(): void + { + Blade::componentNamespace('App\\Http\\ViewComposers\\Components', $this->moduleNameLower); + } +} diff --git a/composer.json b/composer.json index 17770ee2e87c..73d5cb88a644 100644 --- a/composer.json +++ b/composer.json @@ -131,7 +131,8 @@ "app/Helpers/TranslationHelper.php", "app/Helpers/Generic.php", "app/Helpers/ClientPortal.php" - ] + ], + "classmap": ["app/PaymentDrivers/Rotessa/vendor/karneaud/omnipay-rotessa/src/Omnipay/Rotessa/"] }, "autoload-dev": { "psr-4": { diff --git a/config/app.php b/config/app.php index f4d5792fa2ca..59b709d0a9b6 100644 --- a/config/app.php +++ b/config/app.php @@ -200,7 +200,7 @@ return [ App\Providers\MultiDBProvider::class, App\Providers\ClientPortalServiceProvider::class, App\Providers\NinjaTranslationServiceProvider::class, - App\Providers\StaticServiceProvider::class, + App\Providers\StaticServiceProvider::class ], /* diff --git a/database/migrations/2024_06_11_231143_add_rotessa_gateway.php b/database/migrations/2024_06_11_231143_add_rotessa_gateway.php new file mode 100644 index 000000000000..eaade6bb4357 --- /dev/null +++ b/database/migrations/2024_06_11_231143_add_rotessa_gateway.php @@ -0,0 +1,56 @@ +first(); + $count = (int) Gateway::count(); + + $configuration = new \stdClass; + $configuration->api_key = ''; + $configuration->test_mode = true; + + if (!$record) { + $gateway = new Gateway; + } else { + $gateway = $record; + } + + $gateway->id = 4002; + $gateway->name = 'Rotessa'; + $gateway->key = Str::lower(Str::random(32)); + $gateway->provider = 'Rotessa'; + $gateway->is_offsite = true; + $gateway->fields = \json_encode($configuration); + $gateway->visible = 1; + $gateway->site_url = "https://rotessa.com"; + $gateway->default_gateway_type_id = 2; + $gateway->save(); + + Gateway::query()->where('name','=', 'Rotessa')->update(['visible' => 1]); + + \DB::statement('SET FOREIGN_KEY_CHECKS=1;'); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Gateway::where('name', '=', 'Rotessa')->delete(); + } +}; diff --git a/resources/views/portal/ninja2020/gateways/rotessa/bank_transfer/CA/details.blade.php b/resources/views/portal/ninja2020/gateways/rotessa/bank_transfer/CA/details.blade.php new file mode 100644 index 000000000000..9492f3036fc1 --- /dev/null +++ b/resources/views/portal/ninja2020/gateways/rotessa/bank_transfer/CA/details.blade.php @@ -0,0 +1,4 @@ +
{{ session('ach_error') }}
++ Enter the information for the bank account +
++ Enter the address information for the account holder +
++ Enter the information for the account holder +
+