mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-09 20:52:56 +01:00
Fixes for Rotessa Import Customers + Payments
This commit is contained in:
parent
5f0caf370d
commit
fe891a4293
@ -33,10 +33,7 @@ class AccountComponent extends Component
|
||||
"authorization_type" => 'Online'
|
||||
];
|
||||
|
||||
public array $account;
|
||||
|
||||
public function __construct(array $account) {
|
||||
$this->account = $account;
|
||||
public function __construct(public array $account) {
|
||||
$this->attributes = $this->newAttributeBag(Arr::only($this->account, $this->fields) );
|
||||
}
|
||||
|
||||
|
@ -25,10 +25,7 @@ class AddressComponent extends Component
|
||||
'country' => 'US'
|
||||
];
|
||||
|
||||
public array $address;
|
||||
|
||||
public function __construct(array $address) {
|
||||
$this->address = $address;
|
||||
public function __construct(public array $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']);
|
||||
}
|
||||
|
@ -18,9 +18,9 @@ class ContactComponent extends Component
|
||||
|
||||
$contact = collect($contact->client->contacts->firstWhere('is_primary', 1)->toArray())->merge([
|
||||
'home_phone' =>$contact->client->phone,
|
||||
'custom_identifier' => $contact->client->number,
|
||||
'custom_identifier' => $contact->client->client_hash,
|
||||
'name' =>$contact->client->name,
|
||||
'id' => $contact->client->contact_key,
|
||||
'id' => null,
|
||||
] )->all();
|
||||
|
||||
$this->attributes = $this->newAttributeBag(Arr::only($contact, $this->fields) );
|
||||
|
@ -1,123 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\ViewComposers\Components;
|
||||
|
||||
use App\DataProviders\CAProvinces;
|
||||
use App\DataProviders\USStates;
|
||||
use Illuminate\View\Component;
|
||||
use App\Models\ClientContact;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\View\View;
|
||||
|
||||
|
||||
// Contact Component
|
||||
class ContactComponent extends Component
|
||||
{
|
||||
|
||||
public function __construct(ClientContact $contact) {
|
||||
$contact = collect($contact->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) );
|
||||
}
|
||||
}
|
@ -37,11 +37,9 @@ use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
|
||||
|
||||
class PaymentMethod implements MethodInterface
|
||||
{
|
||||
protected RotessaPaymentDriver $rotessa;
|
||||
|
||||
public function __construct(RotessaPaymentDriver $rotessa)
|
||||
public function __construct(protected RotessaPaymentDriver $rotessa)
|
||||
{
|
||||
$this->rotessa = $rotessa;
|
||||
$this->rotessa->init();
|
||||
}
|
||||
|
||||
@ -60,9 +58,6 @@ class PaymentMethod implements MethodInterface
|
||||
'id' => null
|
||||
] )->all();
|
||||
$data['gateway'] = $this->rotessa;
|
||||
// Set gateway type according to client country
|
||||
// $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'));
|
||||
// TODO: detect GatewayType based on client country USA vs CAN
|
||||
$data['gateway_type_id'] = GatewayType::ACSS ;
|
||||
$data['account'] = [
|
||||
'routing_number' => $data['client']->routing_id,
|
||||
@ -104,6 +99,7 @@ class PaymentMethod implements MethodInterface
|
||||
'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'));
|
||||
@ -142,8 +138,10 @@ class PaymentMethod implements MethodInterface
|
||||
*/
|
||||
public function paymentResponse(PaymentResponseRequest $request)
|
||||
{
|
||||
|
||||
$response= null;
|
||||
$customer = null;
|
||||
|
||||
try {
|
||||
$request->validate([
|
||||
'source' => ['required','string','exists:client_gateway_tokens,token'],
|
||||
@ -153,17 +151,20 @@ class PaymentMethod implements MethodInterface
|
||||
$customer = ClientGatewayToken::query()
|
||||
->where('company_gateway_id', $this->rotessa->company_gateway->id)
|
||||
->where('client_id', $this->rotessa->client->id)
|
||||
->where('is_deleted', 0)
|
||||
->where('token', $request->input('source'))
|
||||
->first();
|
||||
|
||||
if(!$customer) throw new \Exception('Client gateway token not found!', SystemLog::TYPE_ROTESSA);
|
||||
|
||||
$transaction = new Transaction($request->only('frequency' ,'installments','amount','process_date') + ['comment' => $this->rotessa->getDescription(false) ]);
|
||||
$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);
|
||||
return $this->processPendingPayment($response->getParameter('id'), (float) $response->getParameter('amount'), PaymentType::ACSS , $customer->token);
|
||||
} catch(\Throwable $e) {
|
||||
$this->processUnsuccessfulPayment( new InvalidResponseException($e->getMessage(), (int) $e->getCode()) );
|
||||
}
|
||||
@ -194,7 +195,7 @@ class PaymentMethod implements MethodInterface
|
||||
/**
|
||||
* Handle unsuccessful payment for Rotessa.
|
||||
*
|
||||
* @param Exception $exception
|
||||
* @param \Exception $exception
|
||||
* @throws PaymentFailed
|
||||
* @return void
|
||||
*/
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace App\PaymentDrivers;
|
||||
|
||||
use App\DataMapper\ClientSettings;
|
||||
use Omnipay\Omnipay;
|
||||
use App\Models\Client;
|
||||
use App\Models\Payment;
|
||||
@ -183,6 +184,9 @@ class RotessaPaymentDriver extends BaseDriver
|
||||
"updated_at": "2015-02-10T23:50:45.000-06:00"
|
||||
}
|
||||
*/
|
||||
$settings = ClientSettings::defaults();
|
||||
$settings->currency_id = $this->company_gateway->company->getSetting('currency_id');
|
||||
|
||||
$client = (\App\Factory\ClientFactory::create($this->company_gateway->company_id, $this->company_gateway->user_id))->fill(
|
||||
[
|
||||
'address1' => $customer->address['address_1'] ?? '',
|
||||
@ -192,7 +196,8 @@ class RotessaPaymentDriver extends BaseDriver
|
||||
'state' => $customer->address['province_code'] ?? '',
|
||||
'country_id' => empty($customer->transit_number) ? 840 : 124,
|
||||
'routing_id' => empty(($r = $customer->routing_number))? null : $r,
|
||||
"number" => str_pad($customer->account_number,3,'0',STR_PAD_LEFT)
|
||||
"number" => str_pad($customer->account_number,3,'0',STR_PAD_LEFT),
|
||||
"settings" => $settings,
|
||||
]
|
||||
);
|
||||
$client->saveQuietly();
|
||||
@ -234,8 +239,9 @@ class RotessaPaymentDriver extends BaseDriver
|
||||
$existing = ClientGatewayToken::query()
|
||||
->where('company_gateway_id', $this->company_gateway->id)
|
||||
->where('client_id', $this->client->id)
|
||||
->where('is_deleted',0)
|
||||
->orWhere(function (Builder $query) use ($data) {
|
||||
$query->where('token', encrypt(join(".", Arr::only($data, 'id','custom_identifier'))) )
|
||||
$query->where('token', join(".", Arr::only($data, ['id','custom_identifier'])))
|
||||
->where('gateway_customer_reference', Arr::only($data,'id'));
|
||||
})
|
||||
->exists();
|
||||
@ -246,14 +252,15 @@ class RotessaPaymentDriver extends BaseDriver
|
||||
|
||||
$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;
|
||||
// TODO: Check/ Validate postal code between USA vs CAN
|
||||
$payment_method_id = GatewayType::ACSS;
|
||||
$gateway_token = $this->storeGatewayToken( [
|
||||
'payment_meta' => $data + ['brand' => 'Rotessa', 'last4' => $data['bank_name'], 'type' => $data['bank_account_type'] ],
|
||||
'token' => encrypt(join(".", Arr::only($data, 'id','custom_identifier'))),
|
||||
'payment_meta' => $data + ['brand' => 'Bank Transfer', 'last4' => substr($data['account_number'], -4), 'type' => GatewayType::ACSS ],
|
||||
'token' => join(".", Arr::only($data, ['id','custom_identifier'])),
|
||||
'payment_method_id' => $payment_method_id ,
|
||||
], ['gateway_customer_reference' =>
|
||||
$data['id']
|
||||
|
46
composer.lock
generated
46
composer.lock
generated
@ -535,16 +535,16 @@
|
||||
},
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
"version": "3.316.10",
|
||||
"version": "3.317.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||
"reference": "eeb8df6ff6caa428e8bcd631ad2a96430900a249"
|
||||
"reference": "6d46c8e00c22f66349b8a509bd2c5ced72cceff2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/eeb8df6ff6caa428e8bcd631ad2a96430900a249",
|
||||
"reference": "eeb8df6ff6caa428e8bcd631ad2a96430900a249",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/6d46c8e00c22f66349b8a509bd2c5ced72cceff2",
|
||||
"reference": "6d46c8e00c22f66349b8a509bd2c5ced72cceff2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -624,9 +624,9 @@
|
||||
"support": {
|
||||
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
|
||||
"issues": "https://github.com/aws/aws-sdk-php/issues",
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.316.10"
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.317.0"
|
||||
},
|
||||
"time": "2024-07-30T18:10:20+00:00"
|
||||
"time": "2024-08-01T18:12:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
@ -4758,16 +4758,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/pint",
|
||||
"version": "v1.17.0",
|
||||
"version": "v1.17.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/pint.git",
|
||||
"reference": "4dba80c1de4b81dc4c4fb10ea6f4781495eb29f5"
|
||||
"reference": "b5b6f716db298671c1dfea5b1082ec2c0ae7064f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/pint/zipball/4dba80c1de4b81dc4c4fb10ea6f4781495eb29f5",
|
||||
"reference": "4dba80c1de4b81dc4c4fb10ea6f4781495eb29f5",
|
||||
"url": "https://api.github.com/repos/laravel/pint/zipball/b5b6f716db298671c1dfea5b1082ec2c0ae7064f",
|
||||
"reference": "b5b6f716db298671c1dfea5b1082ec2c0ae7064f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -4820,7 +4820,7 @@
|
||||
"issues": "https://github.com/laravel/pint/issues",
|
||||
"source": "https://github.com/laravel/pint"
|
||||
},
|
||||
"time": "2024-07-23T16:40:20+00:00"
|
||||
"time": "2024-08-01T09:06:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/prompts",
|
||||
@ -16968,16 +16968,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.11.8",
|
||||
"version": "1.11.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec"
|
||||
"reference": "e370bcddadaede0c1716338b262346f40d296f82"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec",
|
||||
"reference": "6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/e370bcddadaede0c1716338b262346f40d296f82",
|
||||
"reference": "e370bcddadaede0c1716338b262346f40d296f82",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -17022,7 +17022,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-07-24T07:01:22+00:00"
|
||||
"time": "2024-08-01T16:25:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
@ -19031,16 +19031,16 @@
|
||||
},
|
||||
{
|
||||
"name": "spatie/flare-client-php",
|
||||
"version": "1.7.0",
|
||||
"version": "1.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/spatie/flare-client-php.git",
|
||||
"reference": "097040ff51e660e0f6fc863684ac4b02c93fa234"
|
||||
"reference": "180f8ca4c0d0d6fc51477bd8c53ce37ab5a96122"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/spatie/flare-client-php/zipball/097040ff51e660e0f6fc863684ac4b02c93fa234",
|
||||
"reference": "097040ff51e660e0f6fc863684ac4b02c93fa234",
|
||||
"url": "https://api.github.com/repos/spatie/flare-client-php/zipball/180f8ca4c0d0d6fc51477bd8c53ce37ab5a96122",
|
||||
"reference": "180f8ca4c0d0d6fc51477bd8c53ce37ab5a96122",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -19058,7 +19058,7 @@
|
||||
"phpstan/extension-installer": "^1.1",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.0",
|
||||
"phpstan/phpstan-phpunit": "^1.0",
|
||||
"spatie/phpunit-snapshot-assertions": "^4.0|^5.0"
|
||||
"spatie/pest-plugin-snapshots": "^1.0|^2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
@ -19088,7 +19088,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/spatie/flare-client-php/issues",
|
||||
"source": "https://github.com/spatie/flare-client-php/tree/1.7.0"
|
||||
"source": "https://github.com/spatie/flare-client-php/tree/1.8.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -19096,7 +19096,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-06-12T14:39:14+00:00"
|
||||
"time": "2024-08-01T08:27:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/ignition",
|
||||
|
Loading…
Reference in New Issue
Block a user