1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-18 23:42:25 +02:00

Merge branch 'v5-develop' into feature-inbound-email-expenses

Signed-off-by: David Bomba <turbo124@gmail.com>
This commit is contained in:
David Bomba 2024-09-16 16:55:52 +10:00 committed by GitHub
commit 40ebad7dca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
297 changed files with 13786 additions and 10383 deletions

View File

@ -18,7 +18,7 @@ jobs:
phpunit-versions: ['latest']
ci_node_total: [ 8 ]
ci_node_index: [ 0, 1, 2, 3, 4, 5, 6, 7]
laravel: [10.*]
laravel: [11.*]
dependency-version: [prefer-stable]
env:
@ -103,7 +103,6 @@ jobs:
restore-keys: |
${{ runner.os }}-${{ matrix.php }}-composer-
- name: Install composer dependencies
run: |
composer config -g github-oauth.github.com ${{ secrets.GITHUB_TOKEN }}

View File

@ -16,13 +16,6 @@ namespace App\DataMapper;
*/
class BaseSettings
{
// //@deprecated
// public function __construct($obj)
// {
// // foreach ($obj as $key => $value) {
// // $obj->{$key} = $value;
// // }
// }
public static function setCasts($obj, $casts)
{

View File

@ -522,8 +522,6 @@ class CompanySettings extends BaseSettings
public string $email_template_payment_failed = '';
public static $casts = [
'email_template_payment_failed' => 'string',
'email_subject_payment_failed' => 'string',
'payment_flow' => 'string',
'enable_quote_reminder1' => 'bool',
'quote_num_days_reminder1' => 'int',
@ -774,6 +772,8 @@ class CompanySettings extends BaseSettings
'portal_custom_js' => 'string',
'client_portal_enable_uploads' => 'bool',
'purchase_order_number_counter' => 'integer',
'email_template_payment_failed' => 'string',
'email_subject_payment_failed' => 'string',
];
public static $free_plan_casts = [

View File

@ -140,7 +140,7 @@ class EmailTemplateDefaults
public static function emailPaymentFailedTemplate()
{
return '<p>$client<br><br>'.ctrans('texts.client_payment_failure_body', ['invoice' => '$number', 'amount' => '$amount']).'</p><div>$payment_error</div><br><div>$payment_button</div>';
return '<p>$client<br><br>'.ctrans('texts.client_payment_failure_body', ['invoice' => '$number', 'amount' => '$amount']).'</p><div>$payment_error</div><br><div>$view_button</div>';
}
public static function emailQuoteReminder1Subject()

View File

@ -48,6 +48,9 @@ class BaseRule implements RuleInterface
'DK', // Denmark
'EE', // Estonia
'ES', // Spain
'ES-CN', // Canary Islands
'ES-CE', // Ceuta
'ES-ML', // Melilla
'FI', // Finland
'FR', // France
'GR', // Greece
@ -78,6 +81,9 @@ class BaseRule implements RuleInterface
'DK' => 'EU', // Denmark
'EE' => 'EU', // Estonia
'ES' => 'EU', // Spain
'ES-CN' => 'EU', // Canary Islands
'ES-CE' => 'EU', // Ceuta
'ES-ML' => 'EU', // Melilla
'FI' => 'EU', // Finland
'FR' => 'EU', // France
'GR' => 'EU', // Greece

View File

@ -0,0 +1,44 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Tax\ES_CE;
use App\DataMapper\Tax\DE\Rule as DERule;
class Rule extends DERule
{
/** @var string $seller_region */
public string $seller_region = 'EU';
/** @var bool $consumer_tax_exempt */
public bool $consumer_tax_exempt = false;
/** @var bool $business_tax_exempt */
public bool $business_tax_exempt = false;
/** @var bool $eu_business_tax_exempt */
public bool $eu_business_tax_exempt = true;
/** @var bool $foreign_business_tax_exempt */
public bool $foreign_business_tax_exempt = false;
/** @var bool $foreign_consumer_tax_exempt */
public bool $foreign_consumer_tax_exempt = false;
/** @var float $tax_rate */
public float $tax_rate = 0;
/** @var float $reduced_tax_rate */
public float $reduced_tax_rate = 0;
public string $tax_name1 = 'IGIC';
}

View File

@ -0,0 +1,44 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Tax\ES_CN;
use App\DataMapper\Tax\DE\Rule as DERule;
class Rule extends DERule
{
/** @var string $seller_region */
public string $seller_region = 'EU';
/** @var bool $consumer_tax_exempt */
public bool $consumer_tax_exempt = false;
/** @var bool $business_tax_exempt */
public bool $business_tax_exempt = false;
/** @var bool $eu_business_tax_exempt */
public bool $eu_business_tax_exempt = true;
/** @var bool $foreign_business_tax_exempt */
public bool $foreign_business_tax_exempt = false;
/** @var bool $foreign_consumer_tax_exempt */
public bool $foreign_consumer_tax_exempt = false;
/** @var float $tax_rate */
public float $tax_rate = 0;
/** @var float $reduced_tax_rate */
public float $reduced_tax_rate = 0;
public string $tax_name1 = 'IGIC';
}

View File

@ -0,0 +1,44 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Tax\ES_ML;
use App\DataMapper\Tax\DE\Rule as DERule;
class Rule extends DERule
{
/** @var string $seller_region */
public string $seller_region = 'EU';
/** @var bool $consumer_tax_exempt */
public bool $consumer_tax_exempt = false;
/** @var bool $business_tax_exempt */
public bool $business_tax_exempt = false;
/** @var bool $eu_business_tax_exempt */
public bool $eu_business_tax_exempt = true;
/** @var bool $foreign_business_tax_exempt */
public bool $foreign_business_tax_exempt = false;
/** @var bool $foreign_consumer_tax_exempt */
public bool $foreign_consumer_tax_exempt = false;
/** @var float $tax_rate */
public float $tax_rate = 0;
/** @var float $reduced_tax_rate */
public float $reduced_tax_rate = 0;
public string $tax_name1 = 'IGIC';
}

View File

@ -17,7 +17,7 @@ class TaxModel
public string $seller_subregion = 'CA';
/** @var string $version */
public string $version = 'beta';
public string $version = 'gamma';
/** @var object $regions */
public object $regions;
@ -58,6 +58,32 @@ class TaxModel
$this->version = 'beta';
}
if($this->version == 'beta') {
//CEUTA
$this->regions->EU->subregions->{'ES-CE'} = new \stdClass();
$this->regions->EU->subregions->{'ES-CE'}->tax_rate = 4;
$this->regions->EU->subregions->{'ES-CE'}->tax_name = 'IGIC';
$this->regions->EU->subregions->{'ES-CE'}->reduced_tax_rate = 4;
$this->regions->EU->subregions->{'ES-CE'}->apply_tax = false;
//MELILLA ML 4
$this->regions->EU->subregions->{'ES-ML'} = new \stdClass();
$this->regions->EU->subregions->{'ES-ML'}->tax_rate = 4;
$this->regions->EU->subregions->{'ES-ML'}->tax_name = 'IGIC';
$this->regions->EU->subregions->{'ES-ML'}->reduced_tax_rate = 4;
$this->regions->EU->subregions->{'ES-ML'}->apply_tax = false;
//CANARIAS CN 7/3
$this->regions->EU->subregions->{'ES-CN'} = new \stdClass();
$this->regions->EU->subregions->{'ES-CN'}->tax_rate = 7;
$this->regions->EU->subregions->{'ES-CN'}->tax_name = 'IGIC';
$this->regions->EU->subregions->{'ES-CN'}->reduced_tax_rate = 4;
$this->regions->EU->subregions->{'ES-CN'}->apply_tax = false;
$this->version = 'gamma';
}
return $this;
}
@ -419,6 +445,25 @@ class TaxModel
$this->regions->EU->subregions->ES->reduced_tax_rate = 10;
$this->regions->EU->subregions->ES->apply_tax = false;
$this->regions->EU->subregions->{'ES-CE'} = new \stdClass();
$this->regions->EU->subregions->{'ES-CE'}->tax_rate = 4;
$this->regions->EU->subregions->{'ES-CE'}->tax_name = 'IGIC';
$this->regions->EU->subregions->{'ES-CE'}->reduced_tax_rate = 4;
$this->regions->EU->subregions->{'ES-CE'}->apply_tax = false;
$this->regions->EU->subregions->{'ES-ML'} = new \stdClass();
$this->regions->EU->subregions->{'ES-ML'}->tax_rate = 4;
$this->regions->EU->subregions->{'ES-ML'}->tax_name = 'IGIC';
$this->regions->EU->subregions->{'ES-ML'}->reduced_tax_rate = 4;
$this->regions->EU->subregions->{'ES-ML'}->apply_tax = false;
$this->regions->EU->subregions->{'ES-CN'} = new \stdClass();
$this->regions->EU->subregions->{'ES-CN'}->tax_rate = 7;
$this->regions->EU->subregions->{'ES-CN'}->tax_name = 'IGIC';
$this->regions->EU->subregions->{'ES-CN'}->reduced_tax_rate = 3;
$this->regions->EU->subregions->{'ES-CN'}->apply_tax = false;
$this->regions->EU->subregions->FI = new \stdClass();
$this->regions->EU->subregions->FI->tax_rate = 24;
$this->regions->EU->subregions->FI->tax_name = 'ALV';

22
app/Enum/HttpVerb.php Normal file
View File

@ -0,0 +1,22 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Enum;
enum HttpVerb: string
{
case POST = 'post';
case PUT = 'put';
case GET = 'get';
case PATCH = 'patch';
case DELETE = 'delete';
}

View File

@ -0,0 +1,34 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Exceptions;
use Exception;
class PeppolValidationException extends Exception
{
protected string $field = '';
public function __construct($message, $field, $code = 0, Exception $previous = null)
{
// Store the custom data
$this->field = $field;
// Ensure that everything is assigned properly by calling the parent constructor
parent::__construct($message, $code, $previous);
}
public function getInvalidField()
{
return $this->field;
}
}

View File

@ -101,8 +101,11 @@ class ActivityExport extends BaseExport
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
$this->date_format = DateFormat::find($this->company->settings->date_format_id)->format;
/** @var \App\Models\DateFormat $df */
$df = DateFormat::query()->find($this->company->settings->date_format_id);
$this->date_format = $df->format;
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
}

View File

@ -845,7 +845,7 @@ class BaseExport
/**
* Apply Product Filters
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return Builder
*/
@ -870,7 +870,7 @@ class BaseExport
/**
* Add Client Filter
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param mixed $clients
*
* @return Builder
@ -893,7 +893,7 @@ class BaseExport
/**
* Add Vendor Filter
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $vendors
*
* @return Builder
@ -917,7 +917,7 @@ class BaseExport
/**
* AddProjectFilter
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $projects
*
* @return Builder
@ -941,7 +941,7 @@ class BaseExport
/**
* Add Category Filter
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $expense_categories
*
* @return Builder
@ -966,7 +966,7 @@ class BaseExport
/**
* Add Payment Status Filters
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $status
*
* @return Builder
@ -1024,10 +1024,10 @@ class BaseExport
/**
* Add RecurringInvoice Status Filter
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $status
*
* @return Builder
* @return \Illuminate\Database\Eloquent\Builder
*/
protected function addRecurringInvoiceStatusFilter(Builder $query, string $status): Builder
{
@ -1067,7 +1067,7 @@ class BaseExport
/**
* Add QuoteStatus Filter
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $status
*
* @return Builder
@ -1133,7 +1133,7 @@ class BaseExport
/**
* Add PurchaseOrder Status Filter
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $status
*
* @return Builder
@ -1183,7 +1183,7 @@ class BaseExport
/**
* Add Invoice Status Filter
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $status
* @return Builder
*/
@ -1249,7 +1249,7 @@ class BaseExport
/**
* Add Date Range
*
* @param Builder $query
* @param \Illuminate\Database\Eloquent\Builder $query
* @param ?string $table_name
* @return Builder
*/

View File

@ -68,7 +68,7 @@ class BankTransactionFilters extends QueryFilters
*/
public function client_status(string $value = ''): Builder
{
if (strlen($value) == 0) {
if (strlen($value ?? '') == 0) {
return $this->builder;
}
@ -108,13 +108,24 @@ class BankTransactionFilters extends QueryFilters
}
if (count($debit_or_withdrawal_array) >= 1) {
$query->orWhereIn('base_type', $debit_or_withdrawal_array);
$query->whereIn('base_type', $debit_or_withdrawal_array);
}
});
return $this->builder;
}
public function active_banks(string $value = ''): Builder
{
if (strlen($value) == 0 || $value != 'true') {
return $this->builder;
}
return $this->builder->whereHas('bank_integration', function ($query){
$query->where('is_deleted', 0)->whereNull('deleted_at');
});
}
/**
* Filters the list based on Bank Accounts.

View File

@ -42,6 +42,9 @@ class InvoiceItemSum
'DK', // Denmark
'EE', // Estonia
'ES', // Spain
'ES-CE',
'ES-CN',
'ES-ML',
'FI', // Finland
'FR', // France
'GR', // Greece
@ -72,6 +75,9 @@ class InvoiceItemSum
'DK', // Denmark
'EE', // Estonia
'ES', // Spain
'ES-CE',
'ES-CN',
'ES-ML',
'FI', // Finland
'FR', // France
'GR', // Greece
@ -182,7 +188,7 @@ class InvoiceItemSum
/** @var \App\DataMapper\Tax\BaseRule $class */
$class = "App\DataMapper\Tax\\".$this->client->company->country()->iso_3166_2."\\Rule";
$class = "App\DataMapper\Tax\\".str_replace("-","_",$this->client->company->country()->iso_3166_2)."\\Rule";
$this->rule = new $class();

View File

@ -86,6 +86,9 @@ class InvoiceController extends Controller
return render('invoices.show-fullscreen', $data);
}
if(!$invoice->isPayable())
return $this->render('invoices.show',$data);
return auth()->guard('contact')->user()->client->getSetting('payment_flow') == 'default' ? $this->render('invoices.show', $data) : $this->render('invoices.show_smooth', $data);
// return $this->render('invoices.show_smooth', $data);

View File

@ -108,12 +108,6 @@ class PaymentController extends Controller
*/
public function process(Request $request)
{
// $request->validate([
// 'contact_first_name' => ['required'],
// 'contact_last_name' => ['required'],
// 'contact_email' => ['required', 'email'],
// ]);
return (new InstantPayment($request))->run();
}
@ -123,13 +117,7 @@ class PaymentController extends Controller
$gateway = CompanyGateway::findOrFail($request->input('company_gateway_id'));
$payment_hash = PaymentHash::with('fee_invoice')->where('hash', $request->payment_hash)->firstOrFail();
// if($payment_hash)
$invoice = $payment_hash->fee_invoice;
// else
// $invoice = Invoice::with('client')->where('id',$payment_hash->fee_invoice_id)->orderBy('id','desc')->first();
// $invoice = Invoice::with('client')->find($payment_hash->fee_invoice_id);
$client = $invoice ? $invoice->client : auth()->guard('contact')->user()->client;

View File

@ -56,8 +56,8 @@ class PaymentMethodController extends Controller
$data['gateway'] = $gateway;
/** @var \App\Models\ClientContact auth()->user() **/
$client_contact = auth()->user();
/** @var \App\Models\ClientContact auth()->guard('contact')->user() **/
$client_contact = auth()->guard('contact')->user();
$data['client'] = $client_contact->client;
return $gateway
@ -77,8 +77,8 @@ class PaymentMethodController extends Controller
{
$gateway = $this->getClientGateway();
/** @var \App\Models\ClientContact auth()->user() **/
$client_contact = auth()->user();
/** @var \App\Models\ClientContact auth()->guard('contact')->user() **/
$client_contact = auth()->guard('contact')->user();
return $gateway
->driver($client_contact->client)
@ -103,8 +103,8 @@ class PaymentMethodController extends Controller
public function verify(ClientGatewayToken $payment_method)
{
/** @var \App\Models\ClientContact auth()->user() **/
$client_contact = auth()->user();
/** @var \App\Models\ClientContact auth()->guard('contact')->user() **/
$client_contact = auth()->guard('contact')->user();
return $payment_method->gateway
->driver($client_contact->client)
@ -114,8 +114,8 @@ class PaymentMethodController extends Controller
public function processVerification(Request $request, ClientGatewaytoken $payment_method)
{
/** @var \App\Models\ClientContact auth()->user() **/
$client_contact = auth()->user();
/** @var \App\Models\ClientContact auth()->guard('contact')->user() **/
$client_contact = auth()->guard('contact')->user();
return $payment_method->gateway
->driver($client_contact->client)
@ -131,8 +131,8 @@ class PaymentMethodController extends Controller
*/
public function destroy(ClientGatewayToken $payment_method)
{
/** @var \App\Models\ClientContact auth()->user() **/
$client_contact = auth()->user();
/** @var \App\Models\ClientContact auth()->guard('contact')->user() **/
$client_contact = auth()->guard('contact')->user();
if ($payment_method->gateway()->exists()) {
$payment_method->gateway
@ -145,9 +145,19 @@ class PaymentMethodController extends Controller
event(new MethodDeleted($payment_method, auth()->guard('contact')->user()->company, Ninja::eventVars(auth()->guard('contact')->user()->id)));
$payment_method->is_deleted = true;
$payment_method->is_default = false;
$payment_method->delete();
$payment_method->save();
$def_cgt = auth()->guard('contact')->user()->client->gateway_tokens()->orderBy('id','desc')->first();
if($def_cgt)
{
$def_cgt->is_default = true;
$def_cgt->save();
}
} catch (Exception $e) {
nlog($e->getMessage());
@ -161,8 +171,8 @@ class PaymentMethodController extends Controller
private function getClientGateway()
{
/** @var \App\Models\ClientContact auth()->user() **/
$client_contact = auth()->user();
/** @var \App\Models\ClientContact auth()->guard('contact')->user() **/
$client_contact = auth()->guard('contact')->user();
if (request()->query('method') == GatewayType::CREDIT_CARD) {
return $client_contact->client->getCreditCardGateway();

View File

@ -150,6 +150,10 @@ class DocumentController extends BaseController
$document->fill($request->all());
$document->save();
if($document->documentable) { //@phpstan-ignore-line
$document->documentable->touch();
}
return $this->itemResponse($document->fresh());
}

View File

@ -0,0 +1,39 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\Controllers;
use App\Http\Requests\EInvoice\ValidateEInvoiceRequest;
use App\Services\EDocument\Standards\Validation\Peppol\EntityLevel;
class EInvoiceController extends BaseController
{
public function validateEntity(ValidateEInvoiceRequest $request)
{
$el = new EntityLevel();
$data = [];
match($request->entity){
'invoices' => $data = $el->checkInvoice($request->getEntity()),
'clients' => $data = $el->checkClient($request->getEntity()),
'companies' => $data = $el->checkCompany($request->getEntity()),
default => $data['passes'] = false,
};
nlog($data);
return response()->json($data, $data['passes'] ? 200 : 400);
}
}

View File

@ -20,6 +20,7 @@ class GoCardlessController extends Controller
{
public function ibpRedirect(IbpRequest $request)
{
return $request
->getCompanyGateway()
->driver($request->getClient())

View File

@ -475,7 +475,10 @@ class InvoiceController extends BaseController
*/
public function destroy(DestroyInvoiceRequest $request, Invoice $invoice)
{
$this->invoice_repo->delete($invoice);
if (!$invoice->is_deleted) {
$this->invoice_repo->delete($invoice);
}
return $this->itemResponse($invoice->fresh());
}

View File

@ -73,6 +73,10 @@ class OneTimeTokenController extends BaseController
'is_react' => $request->hasHeader('X-REACT') ? true : false,
];
if($request->institution_id) {
$data['institution_id'] = $request->institution_id;
}
Cache::put($hash, $data, 3600);
return response()->json(['hash' => $hash], 200);

View File

@ -17,6 +17,7 @@ use Illuminate\Validation\Rule;
class StoreNoteRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*

View File

@ -136,6 +136,10 @@ class UpdateClientRequest extends Request
$input['shipping_country_id'] = $this->getCountryCode($input['shipping_country_code']);
}
if (isset($input['e_invoice']) && is_array($input['e_invoice'])) {
//ensure it is normalized first!
$input['e_invoice'] = $this->client->filterNullsRecursive($input['e_invoice']);
}
$this->replace($input);
}

View File

@ -130,6 +130,11 @@ class UpdateCompanyRequest extends Request
$input['smtp_verify_peer'] == 'true' ? true : false;
}
if (isset($input['e_invoice']) && is_array($input['e_invoice'])) {
//ensure it is normalized first!
$input['e_invoice'] = $this->company->filterNullsRecursive($input['e_invoice']);
}
$this->replace($input);
}

View File

@ -107,6 +107,7 @@ class StoreCreditRequest extends Request
$input = $this->decodePrimaryKeys($input);
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
$input['line_items'] = $this->cleanFeeItems($input['line_items']);
$input['amount'] = $this->entityTotalAmount($input['line_items']);
if (array_key_exists('exchange_rate', $input) && is_null($input['exchange_rate'])) {

View File

@ -0,0 +1,93 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\Requests\EInvoice;
use App\Utils\Ninja;
use App\Models\Client;
use App\Models\Company;
use App\Models\Invoice;
use App\Http\Requests\Request;
use Illuminate\Validation\Rule;
class ValidateEInvoiceRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize(): bool
{
/** @var \App\Models\User $user */
$user = auth()->user();
$entity = $this->getEntity();
if($entity instanceof Company)
return $entity->id == $user->company()->id;
return $user->can('view', $entity);
}
public function rules()
{
/** @var \App\Models\User $user */
$user = auth()->user();
return [
'entity' => 'required|bail|in:invoices,clients,companies',
'entity_id' => ['required','bail', Rule::exists($this->entity, 'id')
->when($this->entity != 'companies', function ($q) use($user){
$q->where('company_id', $user->company()->id);
})
],
];
}
public function prepareForValidation()
{
$input = $this->all();
if (isset($input['entity_id']) && $input['entity_id'] != null) {
$input['entity_id'] = $this->decodePrimaryKey($input['entity_id']);
}
$this->replace($input);
}
public function getEntity()
{
if(!$this->entity) {
return false;
}
$class = Invoice::class;
match ($this->entity) {
'invoices' => $class = Invoice::class,
'clients' => $class = Client::class,
'companies' => $class = Company::class,
default => $class = Invoice::class,
};
if($this->entity == 'companies')
return auth()->user()->company();
return $class::withTrashed()->find(is_string($this->entity_id) ? $this->decodePrimaryKey($this->entity_id) : $this->entity_id);
}
}

View File

@ -24,4 +24,23 @@ class DestroyInvoiceRequest extends Request
{
return auth()->user()->can('edit', $this->invoice);
}
public function rules()
{
return [];
}
public function prepareForValidation()
{
/** @var \App\Models\User $user */
$user = auth()->user();
if(\Illuminate\Support\Facades\Cache::has($this->ip()."|".$this->invoice->id."|".$user->company()->company_key))
throw new \App\Exceptions\DuplicatePaymentException('Duplicate request.', 429);
\Illuminate\Support\Facades\Cache::put(($this->ip()."|".$this->invoice->id."|".$user->company()->company_key), true, 1);
}
}

View File

@ -108,6 +108,7 @@ class StoreInvoiceRequest extends Request
if (isset($input['line_items']) && is_array($input['line_items'])) {
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
$input['line_items'] = $this->cleanFeeItems($input['line_items']);
$input['amount'] = $this->entityTotalAmount($input['line_items']);
}
if(isset($input['partial']) && $input['partial'] == 0) {

View File

@ -121,6 +121,11 @@ class UpdateInvoiceRequest extends Request
$client = \App\Models\Client::withTrashed()->find($input['client_id']);
$input['due_date'] = \Illuminate\Support\Carbon::parse($input['date'])->addDays((int)$client->getSetting('payment_terms'))->format('Y-m-d');
}
if (isset($input['e_invoice']) && is_array($input['e_invoice'])) {
//ensure it is normalized first!
$input['e_invoice'] = $this->invoice->filterNullsRecursive($input['e_invoice']);
}
$this->replace($input);
}

View File

@ -70,8 +70,8 @@ class RefundPaymentRequest extends Request
'id' => ['bail','required', new ValidRefundableRequest($input)],
'amount' => ['numeric', 'max:99999999999999'],
'date' => 'required',
'invoices.*.invoice_id' => 'required',
'invoices.*.amount' => 'required',
'invoices.*.invoice_id' => 'required|bail',
'invoices.*.amount' => 'required|bail|gt:0',
'invoices' => new ValidRefundableInvoices($input),
];

View File

@ -95,6 +95,7 @@ class StorePurchaseOrderRequest extends Request
if (isset($input['line_items']) && is_array($input['line_items'])) {
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
$input['line_items'] = $this->cleanFeeItems($input['line_items']);
$input['amount'] = $this->entityTotalAmount($input['line_items']);
}

View File

@ -101,6 +101,7 @@ class StoreQuoteRequest extends Request
if (isset($input['line_items']) && is_array($input['line_items'])) {
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
$input['line_items'] = $this->cleanFeeItems($input['line_items']);
$input['amount'] = $this->entityTotalAmount($input['line_items']);
}
if(isset($input['partial']) && $input['partial'] == 0) {

View File

@ -148,6 +148,8 @@ class StoreRecurringInvoiceRequest extends Request
}
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
$input['line_items'] = $this->cleanFeeItems($input['line_items']);
$input['amount'] = $this->entityTotalAmount($input['line_items']);
if (isset($input['auto_bill'])) {

View File

@ -59,7 +59,7 @@ class CleanStaleInvoiceOrder implements ShouldQueue
Invoice::query()
->withTrashed()
->where('status_id', Invoice::STATUS_SENT)
->where('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
->where('updated_at', '<', now()->subHour())
->where('balance', '>', 0)
->whereJsonContains('line_items', ['type_id' => '3'])

View File

@ -45,7 +45,7 @@ class InvoiceRestoredActivity implements ShouldQueue
$fields = new stdClass();
$user_id = isset($event->event_vars['user_id']) ? $event->event_vars['user_id'] : $event->invitation->invoice->user_id;
$user_id = isset($event->event_vars['user_id']) ? $event->event_vars['user_id'] : $event->invoice->user_id;
$fields->user_id = $user_id;
$fields->invoice_id = $event->invoice->id;

View File

@ -41,7 +41,7 @@ class InvoicePay extends Component
'client_postal_code' => 'postal_code',
'client_country_id' => 'country_id',
'client_shipping_address_line_1' => 'shipping_address1',
'client_shipping_address_line_1' => 'shipping_address1',
'client_shipping_address_line_2' => 'shipping_address2',
'client_shipping_city' => 'shipping_city',
'client_shipping_state' => 'shipping_state',
@ -128,6 +128,8 @@ class InvoicePay extends Component
public function payableAmount($payable_amount)
{
// $this->setContext('payable_invoices.0.amount', Number::parseFloat($payable_amount)); // $this->context['payable_invoices'][0]['amount'] = Number::parseFloat($payable_amount); //TODO DB: check parseFloat()
$this->setContext('amount', $payable_amount);
$this->under_over_payment = false;
}
@ -188,7 +190,7 @@ class InvoicePay extends Component
}
}
}
return $this->required_fields = false;
}
@ -196,6 +198,7 @@ class InvoicePay extends Component
#[Computed()]
public function component(): string
{
if (!$this->terms_accepted) {
return Terms::class;
}
@ -217,6 +220,7 @@ class InvoicePay extends Component
}
return ProcessPayment::class;
}
#[Computed()]
@ -239,12 +243,9 @@ class InvoicePay extends Component
$this->setContext('settings', $settings); // $this->context['settings'] = $settings;
$this->setContext('db', $this->db); // $this->context['db'] = $this->db;
nlog($this->invoices);
if(is_array($this->invoices)) {
if(is_array($this->invoices))
$this->invoices = Invoice::find($this->transformKeys($this->invoices));
}
$invoices = $this->invoices->filter(function ($i) {
$i = $i->service()
->markSent()
@ -273,11 +274,14 @@ class InvoicePay extends Component
'invoice_id' => $i->hashed_id,
'amount' => $i->partial > 0 ? $i->partial : $i->balance,
'formatted_amount' => Number::formatValue($i->partial > 0 ? $i->partial : $i->balance, $i->client->currency()),
'formatted_currency' => Number::formatMoney($i->partial > 0 ? $i->partial : $i->balance, $i->client),
'number' => $i->number,
'date' => $i->translateDate($i->date, $i->client->date_format(), $i->client->locale())
'date' => $i->translateDate($i->date, $i->client->date_format(), $i->client->locale()),
'due_date' => $i->translateDate($i->due_date, $i->client->date_format(), $i->client->locale())
];
})->toArray();
$this->setContext('amount', array_sum(array_column($payable_invoices, 'amount')));
$this->setContext('payable_invoices', $payable_invoices);
}
@ -285,4 +289,13 @@ class InvoicePay extends Component
{
return render('flow2.invoice-pay');
}
public function exception($e, $stopPropagation)
{
nlog($e->getMessage());
$stopPropagation();
}
}

View File

@ -12,9 +12,10 @@
namespace App\Livewire\Flow2;
use App\Utils\Traits\WithSecureContext;
use Livewire\Attributes\On;
use App\Utils\Number;
use Livewire\Component;
use Livewire\Attributes\On;
use App\Utils\Traits\WithSecureContext;
class InvoiceSummary extends Component
{
@ -22,26 +23,64 @@ class InvoiceSummary extends Component
public $invoices;
public $amount;
public function mount()
{
//@TODO for a single invoice - show all details, for multi-invoices, only show the summaries
$this->invoices = $this->getContext()['invoices']; // $this->context['invitation']->invoice;
// $this->invoices = $this->getContext()['invoices']; // $this->context['invitation']->invoice;
$contact = $this->getContext()['contact'];
$this->invoices = $this->getContext()['payable_invoices'];
$this->amount = Number::formatMoney($this->getContext()['amount'], $contact->client);
}
#[On(self::CONTEXT_UPDATE)]
public function onContextUpdate(): void
{
// refactor logic for updating the price for eg if it changes with under/over pay
$contact = $this->getContext()['contact'];
$this->invoices = $this->getContext()['payable_invoices'];
$this->amount = Number::formatMoney($this->getContext()['amount'], $contact->client);
// $this->invoices = $this->getContext()['invoices'];
}
public function downloadDocument($invoice_hashed_id)
{
nlog("here");
$contact = $this->getContext()['contact'];
$_invoices = $this->getContext()['invoices'];
$i = $_invoices->first(function ($i) use($invoice_hashed_id){
return $i->hashed_id == $invoice_hashed_id;
});
$file_name = $i->numberFormatter().'.pdf';
$file = (new \App\Jobs\Entity\CreateRawPdf($i->invitations()->where('client_contact_id', $contact->id)->first()))->handle();
nlog("here");
nlog($file);
$headers = ['Content-Type' => 'application/pdf'];
return response()->streamDownload(function () use ($file) {
echo $file;
}, $file_name, $headers);
$this->invoices = $this->getContext()['invoices'];
}
public function render(): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
{
$contact = $this->getContext()['contact'];
return render('flow2.invoices-summary', [
'invoice' => $this->invoices,
'client' => $this->invoices->first()->client,
'client' => $contact->client,
]);
}
}

View File

@ -75,4 +75,13 @@ class PaymentMethod extends Component
{
return render('flow2.payment-method', ['methods' => $this->methods]);
}
public function exception($e, $stopPropagation)
{
nlog($e->getMessage());
$stopPropagation();
}
}

View File

@ -29,7 +29,7 @@ class ProcessPayment extends Component
private array $payment_data_payload = [];
public $isLoading = true;
public function mount()
{
@ -64,7 +64,7 @@ class ProcessPayment extends Component
->setPaymentHash($responder_data['payload']['ph']);
$this->payment_data_payload = $driver->processPaymentViewData($responder_data['payload']);
$this->payment_view = $driver->livewirePaymentView(
$this->payment_data_payload,
);
@ -83,4 +83,21 @@ class ProcessPayment extends Component
return render($this->payment_view, $this->payment_data_payload);
}
public function exception($e, $stopPropagation)
{
$errors = session()->get('errors', new \Illuminate\Support\ViewErrorBag());
$bag = new \Illuminate\Support\MessageBag();
$bag->add('gateway_error', $e->getMessage());
session()->put('errors', $errors->put('default', $bag));
$invoice_id = $this->getContext()['payable_invoices'][0]['invoice_id'];
$this->redirectRoute('client.invoice.show', ['invoice' => $invoice_id]);
$stopPropagation();
}
}

View File

@ -44,6 +44,8 @@ class RequiredFields extends Component
public ?string $client_custom_value3;
public ?string $client_custom_value4;
public $contact;
/** @var array<int, string> */
public array $fields = [];
@ -63,7 +65,7 @@ class RequiredFields extends Component
->with('company')
->find($this->getContext()['company_gateway_id']);
$contact = auth()->user();
$contact = auth()->guard('contact')->user();
$this->client_name = $contact->client->name;
$this->contact_first_name = $contact->first_name;
@ -111,10 +113,10 @@ class RequiredFields extends Component
$rff = new RFFService(
fields: $this->fields,
database: $this->getContext()['db'],
company_gateway_id: (string) $this->company_gateway->id,
company_gateway_id: (string)$this->company_gateway->id,
);
$contact = auth()->user();
$contact = auth()->guard('contact')->user();
/** @var \App\Models\ClientContact $contact */
$errors = $rff->handleSubmit($data, $contact, return_errors: true, callback: function () {
@ -133,4 +135,5 @@ class RequiredFields extends Component
'contact' => $this->getContext()['contact'],
]);
}
}

View File

@ -18,6 +18,7 @@ use Livewire\Component;
class UnderOverPayment extends Component
{
use WithSecureContext;
public $payableAmount;
@ -44,28 +45,30 @@ class UnderOverPayment extends Component
$settings = $this->getContext()['settings'];
foreach($payableInvoices as $key => $invoice) {
foreach($payableInvoices as $key => $invoice){
$payableInvoices[$key]['amount'] = Number::parseFloat($invoice['formatted_amount']);
$payableInvoices[$key]['formatted_currency'] = Number::FormatMoney($payableInvoices[$key]['amount'], $this->getContext()['invitation']->contact->client);
}
$input_amount = collect($payableInvoices)->sum('amount');
if($settings->client_portal_allow_under_payment && $settings->client_portal_under_payment_minimum != 0) {
if($input_amount <= $settings->client_portal_under_payment_minimum) {
if($settings->client_portal_allow_under_payment && $settings->client_portal_under_payment_minimum != 0)
{
if($input_amount <= $settings->client_portal_under_payment_minimum){
// return error message under payment too low.
$this->errors = ctrans('texts.minimum_required_payment', ['amount' => $settings->client_portal_under_payment_minimum]);
$this->dispatch('errorMessageUpdate', errors: $this->errors);
}
}
if(!$settings->client_portal_allow_over_payment && ($input_amount > $this->invoice_amount)) {
if(!$settings->client_portal_allow_over_payment && ($input_amount > $this->invoice_amount)){
$this->errors = ctrans('texts.over_payments_disabled');
$this->dispatch('errorMessageUpdate', errors: $this->errors);
}
if(!$this->errors) {
if(!$this->errors){
$this->setContext('payable_invoices', $payableInvoices);
$this->dispatch('payable-amount', payable_amount: $input_amount);
$this->dispatch('payable-amount', payable_amount: $input_amount );
}
}

View File

@ -51,14 +51,14 @@ class OtpCode extends Mailable
return $this->from(config('mail.from.address'), config('mail.from.name'))
->subject(ctrans('texts.otp_code_subject'))
->text('email.admin.generic_text')
->view('email.admin.generic')
->view('email.client.generic')
->with([
'settings' => $this->company->settings,
'logo' => $this->company->present()->logo(),
'title' => ctrans('texts.otp_code_subject'),
'content' => ctrans('texts.otp_code_body', ['code' => $this->code]),
'whitelabel' => $this->company->account->isPaid(),
'url' => '',
'url' => false,
'button' => false,
'template' => $this->company->account->isPremium() ? 'email.template.admin_premium' : 'email.template.admin',
]);

View File

@ -306,19 +306,19 @@ class BaseModel extends Model
/**
* arrayFilterRecursive
* arrayFilterRecursive nee filterNullsRecursive
*
* Removes null properties from an array
*
* @param array $array
* @return array
*/
public function arrayFilterRecursive(array $array): array
public function filterNullsRecursive(array $array): array
{
foreach ($array as $key => $value) {
if (is_array($value)) {
// Recursively filter the nested array
$array[$key] = $this->arrayFilterRecursive($value);
$array[$key] = $this->filterNullsRecursive($value);
}
// Remove null values
if (is_null($array[$key])) {

View File

@ -661,7 +661,8 @@ class Client extends BaseModel implements HasLocalePreference
}
}
if ($this->currency()->code == 'CAD' && in_array(GatewayType::ACSS, array_column($pms, 'gateway_type_id'))) {
if (in_array($this->currency()->code, ['CAD','USD']) && in_array(GatewayType::ACSS, array_column($pms, 'gateway_type_id'))) {
// if ($this->currency()->code == 'CAD' && in_array(GatewayType::ACSS, array_column($pms, 'gateway_type_id'))) {
foreach ($pms as $pm) {
if ($pm['gateway_type_id'] == GatewayType::ACSS) {
$cg = CompanyGateway::query()->find($pm['company_gateway_id']);
@ -673,6 +674,20 @@ class Client extends BaseModel implements HasLocalePreference
}
}
if (in_array($this->currency()->code, ['GBP']) && in_array(GatewayType::BACS, array_column($pms, 'gateway_type_id'))) {
// if ($this->currency()->code == 'CAD' && in_array(GatewayType::ACSS, array_column($pms, 'gateway_type_id'))) {
foreach ($pms as $pm) {
if ($pm['gateway_type_id'] == GatewayType::BACS) {
$cg = CompanyGateway::query()->find($pm['company_gateway_id']);
if ($cg && $cg->fees_and_limits->{GatewayType::BACS}->is_enabled) {
return $cg;
}
}
}
}
return null;
}

View File

@ -475,7 +475,7 @@ class Company extends BaseModel
public function bank_transactions(): HasMany
{
return $this->hasMany(BankTransaction::class);
return $this->hasMany(BankTransaction::class)->withTrashed();
}
public function bank_transaction_rules(): HasMany

View File

@ -85,6 +85,10 @@ class Document extends BaseModel
'deleted_at' => 'timestamp',
];
protected $touches = [
// 'documentable'
];
/**
* @var array
*/

View File

@ -21,6 +21,7 @@ use App\Models\PaymentHash;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\AuthorizePaymentDriver;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\Utils\Traits\MakesHash;
use net\authorize\api\contract\v1\DeleteCustomerPaymentProfileRequest;
use net\authorize\api\contract\v1\DeleteCustomerProfileRequest;
@ -30,7 +31,7 @@ use net\authorize\api\controller\DeleteCustomerProfileController;
/**
* Class AuthorizeCreditCard.
*/
class AuthorizeCreditCard
class AuthorizeCreditCard implements LivewireMethodInterface
{
use MakesHash;
@ -41,7 +42,7 @@ class AuthorizeCreditCard
$this->authorize = $authorize;
}
public function processPaymentView($data)
public function paymentData(array $data): array
{
$tokens = ClientGatewayToken::where('client_id', $this->authorize->client->id)
->where('company_gateway_id', $this->authorize->company_gateway->id)
@ -54,6 +55,13 @@ class AuthorizeCreditCard
$data['public_client_id'] = $this->authorize->init()->getPublicClientKey();
$data['api_login_id'] = $this->authorize->company_gateway->getConfigField('apiLoginId');
return $data;
}
public function processPaymentView($data)
{
$data = $this->paymentData($data);
return render('gateways.authorize.credit_card.pay', $data);
}
@ -313,4 +321,9 @@ class AuthorizeCreditCard
'invoices' => $vars['invoices'],
];
}
public function livewirePaymentView(array $data): string
{
return 'gateways.authorize.credit_card.pay_livewire';
}
}

View File

@ -14,6 +14,7 @@ namespace App\PaymentDrivers\BTCPay;
use App\Models\Payment;
use App\PaymentDrivers\BTCPayPaymentDriver;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\Utils\Traits\MakesHash;
use App\PaymentDrivers\Common\MethodInterface;
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
@ -24,7 +25,7 @@ use App\Services\Email\EmailObject;
use App\Services\Email\Email;
use Illuminate\Support\Facades\App;
class BTCPay implements MethodInterface
class BTCPay implements MethodInterface, LivewireMethodInterface
{
use MakesHash;
@ -49,9 +50,7 @@ class BTCPay implements MethodInterface
public function paymentView($data)
{
$data['gateway'] = $this->driver_class;
$data['amount'] = $data['total']['amount_with_fee'];
$data['currency'] = $this->driver_class->client->getCurrencyCode();
$data = $this->paymentData($data);
return render('gateways.btcpay.pay', $data);
}
@ -176,4 +175,24 @@ class BTCPay implements MethodInterface
throw new PaymentFailed('Error during BTCPay refund : ' . $e->getMessage());
}
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
return 'gateways.btcpay.pay_livewire';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$data['gateway'] = $this->driver_class;
$data['amount'] = $data['total']['amount_with_fee'];
$data['currency'] = $this->driver_class->client->getCurrencyCode();
return $data;
}
}

View File

@ -404,14 +404,18 @@ class BaseDriver extends AbstractPaymentDriver
$item->gross_line_total = round($item->gross_line_total, 2);
return $item;
})
->whereIn('type_id', ['3','4'])
->where('gross_line_total', round($fee_total,2))
->whereIn('type_id', ['3'])
->where('gross_line_total', '<=', round($fee_total,2))
->count();
if($invoice && $fee_count == 0){
nlog("apparently no fee, so injecting here!");
if(!$invoice->uses_inclusive_taxes){ //must account for taxes! ? line item taxes also
$fee_total = round($fee_total/(1 + (($invoice->tax_rate1+$invoice->tax_rate2+$invoice->tax_rate3)/100)),2);
}
$balance = $invoice->balance;
App::forgetInstance('translator');
@ -426,7 +430,7 @@ class BaseDriver extends AbstractPaymentDriver
$invoice_item->quantity = 1;
$invoice_item->cost = (float)$fee_total;
$invoice_items = (array) $invoice->line_items;
$invoice_items = $invoice->line_items;
$invoice_items[] = $invoice_item;
if (isset($data['gateway_type_id']) && $fees_and_limits = $this->company_gateway->getFeesAndLimits($data['gateway_type_id'])) {
@ -501,28 +505,28 @@ class BaseDriver extends AbstractPaymentDriver
*/
public function storeGatewayToken(array $data, array $additional = []): ?ClientGatewayToken
{
$company_gateway_token = new ClientGatewayToken();
$company_gateway_token->company_id = $this->client->company->id;
$company_gateway_token->client_id = $this->client->id;
$company_gateway_token->token = $data['token'];
$company_gateway_token->company_gateway_id = $this->company_gateway->id;
$company_gateway_token->gateway_type_id = $data['payment_method_id'];
$company_gateway_token->meta = $data['payment_meta'];
$cgt = new ClientGatewayToken();
$cgt->company_id = $this->client->company->id;
$cgt->client_id = $this->client->id;
$cgt->token = $data['token'];
$cgt->company_gateway_id = $this->company_gateway->id;
$cgt->gateway_type_id = $data['payment_method_id'];
$cgt->meta = $data['payment_meta'];
foreach ($additional as $key => $value) {
$company_gateway_token->{$key} = $value;
$cgt->{$key} = $value;
}
$company_gateway_token->save();
$cgt->save();
if ($this->client->gateway_tokens->count() == 1) {
if ($this->client->gateway_tokens->count() > 1) {
$this->client->gateway_tokens()->update(['is_default' => 0]);
$company_gateway_token->is_default = 1;
$company_gateway_token->save();
}
return $company_gateway_token;
$cgt->is_default = 1;
$cgt->save();
return $cgt;
}
public function processInternallyFailedPayment($gateway, $e)
@ -639,7 +643,7 @@ class BaseDriver extends AbstractPaymentDriver
$message = [
'server_response' => $response,
'data' => $this->payment_hash->data,
'data' => $this->payment_hash?->data,
];
SystemLogger::dispatch(
@ -656,6 +660,16 @@ class BaseDriver extends AbstractPaymentDriver
}
}
public function livewirePaymentView(array $data): string
{
return $this->payment_method->livewirePaymentView($data);
}
public function processPaymentViewData(array $data): array
{
return $this->payment_method->paymentData($data);
}
public function checkRequirements()
{
if ($this->company_gateway->require_billing_address) {

View File

@ -12,19 +12,23 @@
namespace App\PaymentDrivers\Braintree;
use App\Exceptions\PaymentFailed;
use App\Http\Controllers\ClientPortal\InvoiceController;
use App\Http\Requests\ClientPortal\Invoices\ProcessInvoicesInBulkRequest;
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
use App\Jobs\Util\SystemLogger;
use App\Models\ClientGatewayToken;
use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentHash;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\BraintreePaymentDriver;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\Common\MethodInterface;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Request;
class ACH implements MethodInterface
class ACH implements MethodInterface, LivewireMethodInterface
{
use MakesHash;
@ -52,7 +56,7 @@ class ACH implements MethodInterface
}
public function authorizeResponse(Request $request)
{
{
$request->validate([
'nonce' => ['required'],
'gateway_type_id' => ['required'],
@ -86,6 +90,22 @@ class ACH implements MethodInterface
$this->braintree->storeGatewayToken($data, ['gateway_customer_reference' => $customer->id]);
if ($request->authorize_then_redirect) {
$this->braintree->payment_hash = PaymentHash::where('hash', $request->payment_hash)->firstOrFail();
$data = [
'invoices' => collect($this->braintree->payment_hash->data->invoices)->map(fn ($invoice) => $invoice->invoice_id)->toArray(),
'action' => 'payment',
];
$request = new ProcessInvoicesInBulkRequest();
$request->replace($data);
session()->flash('message', ctrans('texts.payment_method_added'));
return app(InvoiceController::class)->bulk($request);
}
return redirect()->route('client.payment_methods.index')->withMessage(ctrans('texts.payment_method_added'));
} catch (\Exception $e) {
return $this->braintree->processInternallyFailedPayment($this->braintree, $e);
@ -97,10 +117,11 @@ class ACH implements MethodInterface
public function paymentView(array $data)
{
$data['gateway'] = $this->braintree;
$data['currency'] = $this->braintree->client->getCurrencyCode();
$data['payment_method_id'] = GatewayType::BANK_TRANSFER;
$data['amount'] = $this->braintree->payment_hash->data->amount_with_fee;
$data = $this->paymentData($data);
if (array_key_exists('authorize_then_redirect', $data)) {
return render('gateways.braintree.ach.authorize', array_merge($data));
}
return render('gateways.braintree.ach.pay', $data);
}
@ -181,4 +202,34 @@ class ACH implements MethodInterface
throw new PaymentFailed($response->transaction->additionalProcessorResponse, $response->transaction->processorResponseCode);
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
if (array_key_exists('authorize_then_redirect', $data)) {
return 'gateways.braintree.ach.authorize_livewire';
}
return 'gateways.braintree.ach.pay_livewire';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$data['gateway'] = $this->braintree;
$data['currency'] = $this->braintree->client->getCurrencyCode();
$data['payment_method_id'] = GatewayType::BANK_TRANSFER;
$data['amount'] = $this->braintree->payment_hash->data->amount_with_fee;
$data['client_token'] = $this->braintree->gateway->clientToken()->generate();
$data['payment_hash'] = $this->braintree->payment_hash->hash;
if (count($data['tokens']) === 0) {
$data['authorize_then_redirect'] = true;
}
return $data;
}
}

View File

@ -21,8 +21,9 @@ use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\BraintreePaymentDriver;
use App\PaymentDrivers\Common\LivewireMethodInterface;
class CreditCard
class CreditCard implements LivewireMethodInterface
{
/**
* @var BraintreePaymentDriver
@ -76,17 +77,7 @@ class CreditCard
public function paymentView(array $data)
{
$data['gateway'] = $this->braintree;
$data['client_token'] = $this->braintree->gateway->clientToken()->generate();
$data['threeds'] = $this->threeDParameters($data);
$data['threeds_enable'] = $this->braintree->company_gateway->getConfigField('threeds') ? "true" : "false";
if ($this->braintree->company_gateway->getConfigField('merchantAccountId')) {
/** https://developer.paypal.com/braintree/docs/reference/request/client-token/generate#merchant_account_id */
$data['client_token'] = $this->braintree->gateway->clientToken()->generate([ //@phpstan-ignore-line
'merchantAccountId' => $this->braintree->company_gateway->getConfigField('merchantAccountId'),
]);
}
$data = $this->paymentData($data);
return render('gateways.braintree.credit_card.pay', $data);
}
@ -278,4 +269,32 @@ class CreditCard
return $this->braintree->processInternallyFailedPayment($this->braintree, $e);
}
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
return 'gateways.braintree.credit_card.pay_livewire';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$data['gateway'] = $this->braintree;
$data['client_token'] = $this->braintree->gateway->clientToken()->generate();
$data['threeds'] = $this->threeDParameters($data);
$data['threeds_enable'] = $this->braintree->company_gateway->getConfigField('threeds') ? "true" : "false";
if ($this->braintree->company_gateway->getConfigField('merchantAccountId')) {
/** https://developer.paypal.com/braintree/docs/reference/request/client-token/generate#merchant_account_id */
$data['client_token'] = $this->braintree->gateway->clientToken()->generate([ // @phpstan-ignore-line
'merchantAccountId' => $this->braintree->company_gateway->getConfigField('merchantAccountId'),
]);
}
return $data;
}
}

View File

@ -10,8 +10,9 @@ use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\BraintreePaymentDriver;
use App\PaymentDrivers\Common\LivewireMethodInterface;
class PayPal
class PayPal implements LivewireMethodInterface
{
/**
* @var BraintreePaymentDriver
@ -45,8 +46,7 @@ class PayPal
*/
public function paymentView(array $data)
{
$data['gateway'] = $this->braintree;
$data['client_token'] = $this->braintree->gateway->clientToken()->generate();
$data = $this->paymentData($data);
return render('gateways.braintree.paypal.pay', $data);
}
@ -188,4 +188,23 @@ class PayPal
return $this->braintree->processInternallyFailedPayment($this->braintree, $e);
}
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
return 'gateways.braintree.paypal.pay_livewire';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$data['gateway'] = $this->braintree;
$data['client_token'] = $this->braintree->gateway->clientToken()->generate();
return $data;
}
}

View File

@ -19,6 +19,7 @@ use App\Models\ClientGatewayToken;
use App\Models\GatewayType;
use App\Models\SystemLog;
use App\PaymentDrivers\CheckoutComPaymentDriver;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\Common\MethodInterface;
use App\Utils\Traits\MakesHash;
use Checkout\CheckoutApiException;
@ -32,7 +33,7 @@ use Illuminate\Contracts\View\Factory;
use Illuminate\Http\Request;
use Illuminate\View\View;
class CreditCard implements MethodInterface
class CreditCard implements MethodInterface, LivewireMethodInterface
{
use Utilities;
use MakesHash;
@ -140,7 +141,7 @@ class CreditCard implements MethodInterface
}
}
public function paymentView($data)
public function paymentData(array $data): array
{
$data['gateway'] = $this->checkout;
$data['company_gateway'] = $this->checkout->company_gateway;
@ -150,9 +151,25 @@ class CreditCard implements MethodInterface
$data['raw_value'] = $data['total']['amount_with_fee'];
$data['customer_email'] = $this->checkout->client->present()->email();
return $data;
}
public function paymentView($data, $livewire = false)
{
$data = $this->paymentData($data);
if ($livewire) {
return render('gateways.checkout.credit_card.pay_livewire', $data);
}
return render('gateways.checkout.credit_card.pay', $data);
}
public function livewirePaymentView(array $data): string
{
return 'gateways.checkout.credit_card.pay_livewire';
}
public function paymentResponse(PaymentResponseRequest $request)
{
$state = [

View File

@ -619,4 +619,9 @@ class CheckoutComPaymentDriver extends BaseDriver
});
}
public function livewirePaymentView(array $data): string
{
return $this->payment_method->livewirePaymentView($data);
}
}

View File

@ -17,10 +17,11 @@ use App\Jobs\Util\SystemLogger;
use App\Models\GatewayType;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\EwayPaymentDriver;
use App\Utils\Traits\MakesHash;
class CreditCard
class CreditCard implements LivewireMethodInterface
{
use MakesHash;
@ -102,11 +103,18 @@ class CreditCard
return $token;
}
public function paymentView($data)
public function paymentData(array $data): array
{
$data['gateway'] = $this->eway_driver;
$data['public_api_key'] = $this->eway_driver->company_gateway->getConfigField('publicApiKey');
return $data;
}
public function paymentView($data)
{
$data = $this->paymentData($data);
return render('gateways.eway.pay', $data);
}
@ -276,4 +284,8 @@ class CreditCard
return $payment;
}
public function livewirePaymentView(array $data): string
{
return 'gateways.eway.pay_livewire';
}
}

View File

@ -19,11 +19,12 @@ use App\Models\Payment;
use App\Models\PaymentHash;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\FortePaymentDriver;
use App\Utils\Traits\MakesHash;
use Illuminate\Support\Facades\Validator;
class ACH
class ACH implements LivewireMethodInterface
{
use MakesHash;
@ -79,10 +80,8 @@ class ACH
public function paymentView(array $data)
{
$this->forte->payment_hash->data = array_merge((array) $this->forte->payment_hash->data, $data);
$this->forte->payment_hash->save();
$data = $this->paymentData($data);
$data['gateway'] = $this->forte;
return render('gateways.forte.ach.pay', $data);
}
@ -147,9 +146,14 @@ class ACH
$this->forte->client,
$this->forte->client->company,
);
$error = Validator::make([], []);
$error->getMessageBag()->add('gateway_error', $response->response->response_desc);
return redirect('client/invoices')->withErrors($error);
return redirect()->route('client.invoice.show', ['invoice' => $payment_hash->fee_invoice->hashed_id])->withErrors($error);
// return response()->redirect('client/invoices')->withErrors($error);
}
SystemLogger::dispatch(
@ -175,4 +179,25 @@ class ACH
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
return 'gateways.forte.ach.pay_livewire';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$this->forte->payment_hash->data = array_merge((array) $this->forte->payment_hash->data, $data);
$this->forte->payment_hash->save();
$data['gateway'] = $this->forte;
return $data;
}
}

View File

@ -20,11 +20,12 @@ use App\Models\Payment;
use App\Models\PaymentHash;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\FortePaymentDriver;
use App\Utils\Traits\MakesHash;
use Illuminate\Support\Facades\Validator;
class CreditCard
class CreditCard implements LivewireMethodInterface
{
use MakesHash;
@ -157,10 +158,8 @@ class CreditCard
public function paymentView(array $data)
{
$this->forte->payment_hash->data = array_merge((array) $this->forte->payment_hash->data, $data);
$this->forte->payment_hash->save();
$data['gateway'] = $this->forte;
$data = $this->paymentData($data);
return render('gateways.forte.credit_card.pay', $data);
}
@ -259,7 +258,10 @@ class CreditCard
);
$error = Validator::make([], []);
$error->getMessageBag()->add('gateway_error', $response->response->response_desc);
return redirect('client/invoices')->withErrors($error);
return redirect()->route('client.invoice.show', ['invoice' => $payment_hash->fee_invoice->hashed_id])->withErrors($error);
// return redirect('client/invoices')->withErrors($error);
}
SystemLogger::dispatch(
@ -287,4 +289,25 @@ class CreditCard
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
return 'gateways.forte.credit_card.pay_livewire';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$this->forte->payment_hash->data = array_merge((array) $this->forte->payment_hash->data, $data);
$this->forte->payment_hash->save();
$data['gateway'] = $this->forte;
return $data;
}
}

View File

@ -20,6 +20,7 @@ use App\Models\Invoice;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\Common\MethodInterface;
use App\PaymentDrivers\GoCardlessPaymentDriver;
use App\Utils\Traits\MakesHash;
@ -31,7 +32,7 @@ use Illuminate\Routing\Redirector;
use Illuminate\View\View;
//@deprecated
class ACH implements MethodInterface
class ACH implements MethodInterface, LivewireMethodInterface
{
use MakesHash;
@ -146,9 +147,7 @@ class ACH implements MethodInterface
*/
public function paymentView(array $data): View
{
$data['gateway'] = $this->go_cardless;
$data['amount'] = $this->go_cardless->convertToGoCardlessAmount($data['total']['amount_with_fee'], $this->go_cardless->client->currency()->precision);
$data['currency'] = $this->go_cardless->client->getCurrencyCode();
$data = $this->paymentData($data);
return render('gateways.gocardless.ach.pay', $data);
}
@ -257,4 +256,23 @@ class ACH implements MethodInterface
throw new PaymentFailed('Failed to process the payment.', 500);
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
return 'gateways.gocardless.ach.pay_livewire';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$data['gateway'] = $this->go_cardless;
$data['amount'] = $this->go_cardless->convertToGoCardlessAmount($data['total']['amount_with_fee'], $this->go_cardless->client->currency()->precision);
$data['currency'] = $this->go_cardless->client->getCurrencyCode();
return $data;
}
}

View File

@ -13,23 +13,25 @@
namespace App\PaymentDrivers\GoCardless;
use App\Exceptions\PaymentFailed;
use App\Http\Controllers\ClientPortal\InvoiceController;
use App\Http\Requests\ClientPortal\Invoices\ProcessInvoicesInBulkRequest;
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
use App\Jobs\Mail\PaymentFailureMailer;
use App\Jobs\Util\SystemLogger;
use App\Models\GatewayType;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\PaymentHash;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\Common\MethodInterface;
use App\PaymentDrivers\GoCardlessPaymentDriver;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\View\View;
class DirectDebit implements MethodInterface
class DirectDebit implements MethodInterface, LivewireMethodInterface
{
use MakesHash;
@ -93,6 +95,8 @@ class DirectDebit implements MethodInterface
'method' => GatewayType::DIRECT_DEBIT,
'session_token' => $session_token,
'billing_request' => $response->id,
'authorize_then_redirect' => true,
'payment_hash' => $this->go_cardless->payment_hash?->hash,
]),
"exit_uri" => $exit_uri,
"links" => [
@ -142,7 +146,6 @@ class DirectDebit implements MethodInterface
*/
public function authorizeResponse(Request $request)
{
try {
$billing_request = $this->go_cardless->gateway->billingRequests()->get($request->billing_request);
@ -165,6 +168,22 @@ class DirectDebit implements MethodInterface
nlog($mandate);
if ($request->has('authorize_then_redirect') && $request->payment_hash !== null) {
$this->go_cardless->payment_hash = PaymentHash::where('hash', $request->payment_hash)->firstOrFail();
$data = [
'invoices' => collect($this->go_cardless->payment_hash->data->invoices)->map(fn ($invoice) => $invoice->invoice_id)->toArray(),
'action' => 'payment',
];
$request = new ProcessInvoicesInBulkRequest();
$request->replace($data);
session()->flash('message', ctrans('texts.payment_method_added'));
return app(InvoiceController::class)->bulk($request);
}
return redirect()->route('client.payment_methods.show', $payment_method->hashed_id);
} catch (\Exception $exception) {
@ -214,13 +233,10 @@ class DirectDebit implements MethodInterface
* Payment view for Direct Debit.
*
* @param array $data
* @return \Illuminate\View\View
*/
public function paymentView(array $data): View
public function paymentView(array $data)
{
$data['gateway'] = $this->go_cardless;
$data['amount'] = $this->go_cardless->convertToGoCardlessAmount($data['total']['amount_with_fee'], $this->go_cardless->client->currency()->precision);
$data['currency'] = $this->go_cardless->client->getCurrencyCode();
$data = $this->paymentData($data);
return render('gateways.gocardless.direct_debit.pay', $data);
}
@ -330,4 +346,30 @@ class DirectDebit implements MethodInterface
throw new PaymentFailed('Failed to process the payment.', 500);
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
return 'gateways.gocardless.direct_debit.pay_livewire';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$data['gateway'] = $this->go_cardless;
$data['amount'] = $this->go_cardless->convertToGoCardlessAmount($data['total']['amount_with_fee'], $this->go_cardless->client->currency()->precision);
$data['currency'] = $this->go_cardless->client->getCurrencyCode();
if (count($data['tokens']) === 0) {
$data['authorize_then_redirect'] = true;
$this->authorizeView($data);
}
return $data;
}
}

View File

@ -9,13 +9,14 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\Common\MethodInterface;
use App\PaymentDrivers\GoCardlessPaymentDriver;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class InstantBankPay implements MethodInterface
class InstantBankPay implements MethodInterface, LivewireMethodInterface
{
protected GoCardlessPaymentDriver $go_cardless;
@ -94,12 +95,15 @@ class InstantBankPay implements MethodInterface
public function paymentResponse($request)
{
$this->go_cardless->setPaymentHash(
$request->getPaymentHash()
);
$this->go_cardless->init();
nlog($request->all());
try {
$billing_request = $this->go_cardless->gateway->billingRequests()->get(
$this->go_cardless->payment_hash->data->billing_request
@ -116,12 +120,13 @@ class InstantBankPay implements MethodInterface
return $this->processSuccessfulPayment($payment);
}
if ($billing_request->status === 'submitted') {
if (in_array($billing_request->status, ['fulfilling', 'submitted'])) {
return $this->processPendingPayment($payment);
}
return $this->processUnsuccessfulPayment($payment);
$this->processUnsuccessfulPayment($payment);
} catch (\Exception $exception) {
throw new PaymentFailed(
$exception->getMessage(),
$exception->getCode()
@ -157,7 +162,7 @@ class InstantBankPay implements MethodInterface
$this->go_cardless->client->company,
);
return redirect()->route('client.payments.show', ['payment' => $this->go_cardless->encodePrimaryKey($payment->id)]);
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
}
@ -197,9 +202,8 @@ class InstantBankPay implements MethodInterface
* Process unsuccessful payments for Direct Debit.
*
* @param ResourcesPayment $payment
* @return never
*/
public function processUnsuccessfulPayment(\GoCardlessPro\Resources\Payment $payment)
public function processUnsuccessfulPayment(\GoCardlessPro\Resources\Payment $payment): void
{
PaymentFailureMailer::dispatch($this->go_cardless->client, $payment->status, $this->go_cardless->client->company, $this->go_cardless->payment_hash->data->amount_with_fee);
@ -224,4 +228,24 @@ class InstantBankPay implements MethodInterface
$this->go_cardless->client->company,
);
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
// not supported, this is offsite payment method.
return '';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$this->paymentView($data);
return $data;
}
}

View File

@ -13,13 +13,17 @@
namespace App\PaymentDrivers\GoCardless;
use App\Exceptions\PaymentFailed;
use App\Http\Controllers\ClientPortal\InvoiceController;
use App\Http\Requests\ClientPortal\Invoices\ProcessInvoicesInBulkRequest;
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
use App\Jobs\Util\SystemLogger;
use App\Models\GatewayType;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\PaymentHash;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\Common\MethodInterface;
use App\PaymentDrivers\GoCardlessPaymentDriver;
use App\Utils\Traits\MakesHash;
@ -29,7 +33,7 @@ use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\View\View;
class SEPA implements MethodInterface
class SEPA implements MethodInterface, LivewireMethodInterface
{
use MakesHash;
@ -60,6 +64,8 @@ class SEPA implements MethodInterface
'success_redirect_url' => route('client.payment_methods.confirm', [
'method' => GatewayType::SEPA,
'session_token' => $session_token,
'authorize_then_redirect' => true,
'payment_hash' => $this->go_cardless->payment_hash?->hash,
]),
'prefilled_customer' => [
'given_name' => auth()->guard('contact')->user()->client->present()->first_name(),
@ -131,6 +137,22 @@ class SEPA implements MethodInterface
$payment_method = $this->go_cardless->storeGatewayToken($data, ['gateway_customer_reference' => $redirect_flow->links->customer]);
if ($request->has('authorize_then_redirect') && $request->payment_hash !== null) {
$this->go_cardless->payment_hash = PaymentHash::where('hash', $request->payment_hash)->firstOrFail();
$data = [
'invoices' => collect($this->go_cardless->payment_hash->data->invoices)->map(fn ($invoice) => $invoice->invoice_id)->toArray(),
'action' => 'payment',
];
$request = new ProcessInvoicesInBulkRequest();
$request->replace($data);
session()->flash('message', ctrans('texts.payment_method_added'));
return app(InvoiceController::class)->bulk($request);
}
return redirect()->route('client.payment_methods.show', $payment_method->hashed_id);
} catch (\Exception $exception) {
return $this->processUnsuccessfulAuthorization($exception);
@ -145,9 +167,7 @@ class SEPA implements MethodInterface
*/
public function paymentView(array $data): View
{
$data['gateway'] = $this->go_cardless;
$data['amount'] = $this->go_cardless->convertToGoCardlessAmount($data['total']['amount_with_fee'], $this->go_cardless->client->currency()->precision);
$data['currency'] = $this->go_cardless->client->getCurrencyCode();
$data = $this->paymentData($data);
return render('gateways.gocardless.sepa.pay', $data);
}
@ -257,4 +277,30 @@ class SEPA implements MethodInterface
throw new PaymentFailed('Failed to process the payment.', 500);
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
return 'gateways.gocardless.sepa.pay_livewire';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$data['gateway'] = $this->go_cardless;
$data['amount'] = $this->go_cardless->convertToGoCardlessAmount($data['total']['amount_with_fee'], $this->go_cardless->client->currency()->precision);
$data['currency'] = $this->go_cardless->client->getCurrencyCode();
if (count($data['tokens']) === 0) {
$data['authorize_then_redirect'] = true;
$this->authorizeView($data);
}
return $data;
}
}

View File

@ -256,7 +256,7 @@ class GoCardlessPaymentDriver extends BaseDriver
$this->init();
nlog('GoCardless Event');
nlog($request->all());
if (! $request->has('events')) {
nlog('No GoCardless events to process in response?');
@ -266,7 +266,10 @@ class GoCardlessPaymentDriver extends BaseDriver
sleep(1);
foreach ($request->events as $event) {
if ($event['action'] === 'confirmed' || $event['action'] === 'paid_out') {
if (
($event['resource_type'] == 'payments' && $event['action'] == 'confirmed') ||
$event['action'] === 'paid_out')
{
nlog('Searching for transaction reference');
$payment = Payment::query()

View File

@ -19,13 +19,14 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\Common\MethodInterface;
use App\PaymentDrivers\MolliePaymentDriver;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class Bancontact implements MethodInterface
class Bancontact implements MethodInterface, LivewireMethodInterface
{
protected MolliePaymentDriver $mollie;
@ -209,4 +210,24 @@ class Bancontact implements MethodInterface
{
return $this->processSuccessfulPayment($payment, 'open');
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
// Doesn't support, it's offsite payment method.
return '';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$this->paymentView($data);
return $data;
}
}

View File

@ -19,6 +19,7 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\Common\MethodInterface;
use App\PaymentDrivers\MolliePaymentDriver;
use Exception;
@ -28,7 +29,7 @@ use Illuminate\Routing\Redirector;
use Illuminate\View\View;
use Mollie\Api\Resources\Payment as ResourcesPayment;
class BankTransfer implements MethodInterface
class BankTransfer implements MethodInterface, LivewireMethodInterface
{
protected MolliePaymentDriver $mollie;
@ -206,4 +207,24 @@ class BankTransfer implements MethodInterface
{
return $this->processSuccessfulPayment($payment, 'open');
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
// Doesn't support, it's offsite payment method.
return '';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$this->paymentView($data);
return $data;
}
}

View File

@ -10,12 +10,13 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\MolliePaymentDriver;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\View\View;
class CreditCard
class CreditCard implements LivewireMethodInterface
{
/**
* @var MolliePaymentDriver
@ -37,7 +38,7 @@ class CreditCard
*/
public function paymentView(array $data)
{
$data['gateway'] = $this->mollie;
$data = $this->paymentData($data);
return render('gateways.mollie.credit_card.pay', $data);
}
@ -257,4 +258,22 @@ class CreditCard
{
return redirect()->route('client.payment_methods.index');
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
return 'gateways.mollie.credit_card.pay_livewire';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$data['gateway'] = $this->mollie;
return $data;
}
}

View File

@ -19,13 +19,14 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\Common\MethodInterface;
use App\PaymentDrivers\MolliePaymentDriver;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class IDEAL implements MethodInterface
class IDEAL implements MethodInterface, LivewireMethodInterface
{
protected MolliePaymentDriver $mollie;
@ -209,4 +210,24 @@ class IDEAL implements MethodInterface
{
return $this->processSuccessfulPayment($payment, 'open');
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
// Doesn't support, it's offsite payment method.
return '';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$this->paymentView($data);
return $data;
}
}

View File

@ -19,13 +19,14 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\Common\MethodInterface;
use App\PaymentDrivers\MolliePaymentDriver;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class KBC implements MethodInterface
class KBC implements MethodInterface, LivewireMethodInterface
{
protected MolliePaymentDriver $mollie;
@ -193,4 +194,24 @@ class KBC implements MethodInterface
return redirect()->route('client.payments.show', ['payment' => $this->mollie->encodePrimaryKey($payment_record->id)]);
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
// Doesn't support, it's offsite payment method.
return '';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$this->paymentView($data);
return $data;
}
}

View File

@ -18,12 +18,13 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\PayFastPaymentDriver;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
class CreditCard
class CreditCard implements LivewireMethodInterface
{
public $payfast;
@ -158,24 +159,9 @@ class CreditCard
public function paymentView($data)
{
$payfast_data = [
'merchant_id' => $this->payfast->company_gateway->getConfigField('merchantId'),
'merchant_key' => $this->payfast->company_gateway->getConfigField('merchantKey'),
'return_url' => route('client.payments.index'),
'cancel_url' => route('client.payment_methods.index'),
'notify_url' => $this->payfast->genericWebhookUrl(),
'm_payment_id' => $data['payment_hash'],
'amount' => $data['amount_with_fee'],
'item_name' => 'purchase',
'item_description' => ctrans('texts.invoices').': '.collect($data['invoices'])->pluck('invoice_number'),
'passphrase' => $this->payfast->company_gateway->getConfigField('passphrase'),
];
$data = $this->paymentData($data);
$payfast_data['signature'] = $this->payfast->generateSignature($payfast_data);
$payfast_data['gateway'] = $this->payfast;
$payfast_data['payment_endpoint_url'] = $this->payfast->endpointUrl();
return render('gateways.payfast.pay', array_merge($data, $payfast_data));
return render('gateways.payfast.pay', array_merge($data));
}
/*
@ -240,7 +226,7 @@ class CreditCard
$payment = $this->payfast->createPayment($payment_record, Payment::STATUS_COMPLETED);
//return redirect()->route('client.payments.show', ['payment' => $this->payfast->encodePrimaryKey($payment->id)]);
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
}
private function processUnsuccessfulPayment($server_response)
@ -263,4 +249,36 @@ class CreditCard
throw new PaymentFailed('Failed to process the payment.', 500);
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
return 'gateways.payfast.pay_livewire';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$payfast_data = [
'merchant_id' => $this->payfast->company_gateway->getConfigField('merchantId'),
'merchant_key' => $this->payfast->company_gateway->getConfigField('merchantKey'),
'return_url' => route('client.invoice.show',['invoice' => $this->payfast->payment_hash->fee_invoice->hashed_id]), //route('client.payments.index'),
'cancel_url' => route('client.invoice.show',['invoice' => $this->payfast->payment_hash->fee_invoice->hashed_id]), //route('client.payment_methods.index'),
'notify_url' => $this->payfast->genericWebhookUrl(),
'm_payment_id' => $data['payment_hash'],
'amount' => $data['amount_with_fee'],
'item_name' => 'purchase',
'item_description' => ctrans('texts.invoices').': '.collect($data['invoices'])->pluck('invoice_number'),
'passphrase' => $this->payfast->company_gateway->getConfigField('passphrase'),
];
$payfast_data['signature'] = $this->payfast->generateSignature($payfast_data);
$payfast_data['gateway'] = $this->payfast;
$payfast_data['payment_endpoint_url'] = $this->payfast->endpointUrl();
return array_merge($data, $payfast_data);
}
}

View File

@ -85,30 +85,13 @@ class PayPalPPCPPaymentDriver extends PayPalBasePaymentDriver
*/
public function processPaymentView($data)
{
$this->init()->checkPaymentsReceivable();
$data['gateway'] = $this;
$this->payment_hash->data = array_merge((array) $this->payment_hash->data, ['amount' => $data['total']['amount_with_fee']]);
$this->payment_hash->save();
$data['client_id'] = config('ninja.paypal.client_id');
$data['token'] = $this->getClientToken();
$data['order_id'] = $this->createOrder($data);
$data['funding_source'] = $this->paypal_payment_method;
$data['gateway_type_id'] = $this->gateway_type_id;
$data['merchantId'] = $this->company_gateway->getConfigField('merchantId');
$data['currency'] = $this->client->currency()->code;
$data['guid'] = $this->risk_guid;
$data['identifier'] = "s:INN_".$this->company_gateway->getConfigField('merchantId')."_CHCK";
$data['pp_client_reference'] = $this->getClientHash();
$data = $this->processPaymentViewData($data);
if($this->gateway_type_id == 29) {
return render('gateways.paypal.ppcp.card', $data);
} else {
return render('gateways.paypal.ppcp.pay', $data);
}
}
/**
@ -480,7 +463,35 @@ class PayPalPPCPPaymentDriver extends PayPalBasePaymentDriver
}
public function processPaymentViewData(array $data): array
{
$this->init()->checkPaymentsReceivable();
$data['gateway'] = $this;
$this->payment_hash->data = array_merge((array) $this->payment_hash->data, ['amount' => $data['total']['amount_with_fee']]);
$this->payment_hash->save();
$data['client_id'] = config('ninja.paypal.client_id');
$data['token'] = $this->getClientToken();
$data['order_id'] = $this->createOrder($data);
$data['funding_source'] = $this->paypal_payment_method;
$data['gateway_type_id'] = $this->gateway_type_id;
$data['merchantId'] = $this->company_gateway->getConfigField('merchantId');
$data['currency'] = $this->client->currency()->code;
$data['guid'] = $this->risk_guid;
$data['identifier'] = "s:INN_".$this->company_gateway->getConfigField('merchantId')."_CHCK";
$data['pp_client_reference'] = $this->getClientHash();
$data['invoice_hash'] = $this->payment_hash->fee_invoice->hashed_id;
return $data;
}
public function livewirePaymentView(array $data): string
{
if ($this->gateway_type_id == 29) {
return 'gateways.paypal.ppcp.card_livewire';
}
return 'gateways.paypal.ppcp.pay_livewire';
}
}

View File

@ -31,30 +31,13 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver
public function processPaymentView($data)
{
$this->init();
$data['gateway'] = $this;
$this->payment_hash->data = array_merge((array) $this->payment_hash->data, ['amount' => $data['total']['amount_with_fee']]);
$this->payment_hash->save();
$data['client_id'] = $this->company_gateway->getConfigField('clientId');
$data['token'] = $this->getClientToken();
$data['order_id'] = $this->createOrder($data);
$data['funding_source'] = $this->paypal_payment_method;
$data['gateway_type_id'] = $this->gateway_type_id;
$data['currency'] = $this->client->currency()->code;
$data['guid'] = $this->risk_guid;
$data['identifier'] = "s:INN_ACDC_CHCK";
$data['pp_client_reference'] = $this->getClientHash();
$data = $this->processPaymentViewData($data);
if($this->gateway_type_id == 29) {
return render('gateways.paypal.ppcp.card', $data);
} else {
return render('gateways.paypal.pay', $data);
}
}
/**
@ -71,8 +54,6 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver
$request['gateway_response'] = str_replace("Error: ", "", $request['gateway_response']);
$response = json_decode($request['gateway_response'], true);
nlog($response);
if($request->has('token') && strlen($request->input('token')) > 2) {
return $this->processTokenPayment($request, $response);
}
@ -434,4 +415,36 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver
SystemLogger::dispatch($response, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_PAYPAL, $this->client, $this->client->company);
}
public function processPaymentViewData(array $data): array
{
$this->init();
$data['gateway'] = $this;
$this->payment_hash->data = array_merge((array) $this->payment_hash->data, ['amount' => $data['total']['amount_with_fee']]);
$this->payment_hash->save();
$data['client_id'] = $this->company_gateway->getConfigField('clientId');
$data['token'] = $this->getClientToken();
$data['order_id'] = $this->createOrder($data);
$data['funding_source'] = $this->paypal_payment_method;
$data['gateway_type_id'] = $this->gateway_type_id;
$data['currency'] = $this->client->currency()->code;
$data['guid'] = $this->risk_guid;
$data['identifier'] = "s:INN_ACDC_CHCK";
$data['pp_client_reference'] = $this->getClientHash();
$data['invoice_hash'] = $this->payment_hash->fee_invoice->hashed_id;
return $data;
}
public function livewirePaymentView(array $data): string
{
if ($this->gateway_type_id == 29) {
return 'gateways.paypal.ppcp.card_livewire';
}
return 'gateways.paypal.pay_livewire';
}
}

View File

@ -18,12 +18,13 @@ use App\Models\Invoice;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\PaytracePaymentDriver;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class CreditCard
class CreditCard implements LivewireMethodInterface
{
use MakesHash;
@ -36,9 +37,8 @@ class CreditCard
public function authorizeView($data)
{
$data['client_key'] = $this->paytrace->getAuthToken();
$data['gateway'] = $this->paytrace;
$data = $this->paymentData($data);
return render('gateways.paytrace.authorize', $data);
}
@ -239,5 +239,24 @@ class CreditCard
];
return $this->paytrace->processUnsuccessfulTransaction($data);
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
return 'gateways.paytrace.pay_livewire';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$data['client_key'] = $this->paytrace->getAuthToken();
$data['gateway'] = $this->paytrace;
return $data;
}
}

View File

@ -254,7 +254,20 @@ class PaytracePaymentDriver extends BaseDriver
public function getClientRequiredFields(): array
{
$fields = parent::getClientRequiredFields();
$fields = [];
if ($this->company_gateway->require_client_name) {
$fields[] = ['name' => 'client_name', 'label' => ctrans('texts.client_name'), 'type' => 'text', 'validation' => 'required'];
}
$fields[] = ['name' => 'contact_first_name', 'label' => ctrans('texts.first_name'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'contact_last_name', 'label' => ctrans('texts.last_name'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'contact_email', 'label' => ctrans('texts.email'), 'type' => 'text', 'validation' => 'required,email:rfc'];
if ($this->company_gateway->require_client_phone) {
$fields[] = ['name' => 'client_phone', 'label' => ctrans('texts.client_phone'), 'type' => 'tel', 'validation' => 'required'];
}
$fields[] = ['name' => 'client_address_line_1', 'label' => ctrans('texts.address1'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_city', 'label' => ctrans('texts.city'), 'type' => 'text', 'validation' => 'required'];
@ -262,6 +275,35 @@ class PaytracePaymentDriver extends BaseDriver
$fields[] = ['name' => 'client_state', 'label' => ctrans('texts.state'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_country_id', 'label' => ctrans('texts.country'), 'type' => 'text', 'validation' => 'required'];
if ($this->company_gateway->require_shipping_address) {
$fields[] = ['name' => 'client_shipping_address_line_1', 'label' => ctrans('texts.shipping_address1'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_shipping_city', 'label' => ctrans('texts.shipping_city'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_shipping_state', 'label' => ctrans('texts.shipping_state'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_shipping_postal_code', 'label' => ctrans('texts.shipping_postal_code'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_shipping_country_id', 'label' => ctrans('texts.shipping_country'), 'type' => 'text', 'validation' => 'required'];
}
if ($this->company_gateway->require_custom_value1) {
$fields[] = ['name' => 'client_custom_value1', 'label' => $this->helpers->makeCustomField($this->client->company->custom_fields, 'client1'), 'type' => 'text', 'validation' => 'required'];
}
if ($this->company_gateway->require_custom_value2) {
$fields[] = ['name' => 'client_custom_value2', 'label' => $this->helpers->makeCustomField($this->client->company->custom_fields, 'client2'), 'type' => 'text', 'validation' => 'required'];
}
if ($this->company_gateway->require_custom_value3) {
$fields[] = ['name' => 'client_custom_value3', 'label' => $this->helpers->makeCustomField($this->client->company->custom_fields, 'client3'), 'type' => 'text', 'validation' => 'required'];
}
if ($this->company_gateway->require_custom_value4) {
$fields[] = ['name' => 'client_custom_value4', 'label' => $this->helpers->makeCustomField($this->client->company->custom_fields, 'client4'), 'type' => 'text', 'validation' => 'required'];
}
return $fields;
}

View File

@ -19,6 +19,7 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\Common\MethodInterface;
use App\PaymentDrivers\RazorpayPaymentDriver;
use Illuminate\Http\RedirectResponse;
@ -26,7 +27,7 @@ use Illuminate\Http\Request;
use Illuminate\View\View;
use Razorpay\Api\Errors\SignatureVerificationError;
class Hosted implements MethodInterface
class Hosted implements MethodInterface, LivewireMethodInterface
{
protected RazorpayPaymentDriver $razorpay;
@ -67,23 +68,7 @@ class Hosted implements MethodInterface
*/
public function paymentView(array $data): View
{
$order = $this->razorpay->gateway->order->create([
'currency' => $this->razorpay->client->currency()->code,
'amount' => $this->razorpay->convertToRazorpayAmount((float) $this->razorpay->payment_hash->data->amount_with_fee),
]);
$this->razorpay->payment_hash->withData('order_id', $order->id);
$this->razorpay->payment_hash->withData('order_amount', $order->amount);
$data['gateway'] = $this->razorpay;
$data['options'] = [
'key' => $this->razorpay->company_gateway->getConfigField('apiKey'),
'amount' => $this->razorpay->convertToRazorpayAmount((float) $this->razorpay->payment_hash->data->amount_with_fee),
'currency' => $this->razorpay->client->currency()->code,
'name' => $this->razorpay->company_gateway->company->present()->name(),
'order_id' => $order->id,
];
$data = $this->paymentData($data);
return render('gateways.razorpay.hosted.pay', $data);
}
@ -174,4 +159,38 @@ class Hosted implements MethodInterface
throw new PaymentFailed($exception->getMessage(), $exception->getCode());
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
return 'gateways.razorpay.hosted.pay_livewire';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$order = $this->razorpay->gateway->order->create([
'currency' => $this->razorpay->client->currency()->code,
'amount' => $this->razorpay->convertToRazorpayAmount((float) $this->razorpay->payment_hash->data->amount_with_fee),
]);
$this->razorpay->payment_hash->withData('order_id', $order->id);
$this->razorpay->payment_hash->withData('order_amount', $order->amount);
$data['gateway'] = $this->razorpay;
$data['options'] = [
'key' => $this->razorpay->company_gateway->getConfigField('apiKey'),
'amount' => $this->razorpay->convertToRazorpayAmount((float) $this->razorpay->payment_hash->data->amount_with_fee),
'currency' => $this->razorpay->client->currency()->code,
'name' => $this->razorpay->company_gateway->company->present()->name(),
'order_id' => $order->id,
];
return $data;
}
}

View File

@ -12,7 +12,10 @@
namespace App\PaymentDrivers\Rotessa;
use App\Http\Controllers\ClientPortal\InvoiceController;
use App\Http\Requests\ClientPortal\Invoices\ProcessInvoicesInBulkRequest;
use App\Models\Payment;
use App\Models\PaymentHash;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use Illuminate\View\View;
@ -112,8 +115,23 @@ class PaymentMethod implements MethodInterface, LivewireMethodInterface
}
return redirect()->route('client.payment_methods.index')->withMessage(ctrans('texts.payment_method_added'));
if ($request->authorize_then_redirect) {
$this->rotessa->payment_hash = PaymentHash::where('hash', $request->payment_hash)->firstOrFail();
$data = [
'invoices' => collect($this->rotessa->payment_hash->data->invoices)->map(fn ($invoice) => $invoice->invoice_id)->toArray(),
'action' => 'payment',
];
$request = new ProcessInvoicesInBulkRequest();
$request->replace($data);
session()->flash('message', ctrans('texts.payment_method_added'));
return app(InvoiceController::class)->bulk($request);
}
return redirect()->route('client.payment_methods.index')->withMessage(ctrans('texts.payment_method_added'));
}
/**
@ -126,6 +144,10 @@ class PaymentMethod implements MethodInterface, LivewireMethodInterface
{
$data = $this->paymentData($data);
if ($data['authorize_then_redirect']) {
return $this->authorizeView($data);
}
return render('gateways.rotessa.bank_transfer.pay', $data );
}
@ -221,6 +243,10 @@ class PaymentMethod implements MethodInterface, LivewireMethodInterface
*/
public function livewirePaymentView(array $data): string
{
if (array_key_exists('authorize_then_redirect', $data)) {
return 'gateways.rotessa.bank_transfer.authorize_livewire';
}
return 'gateways.rotessa.bank_transfer.pay_livewire';
}
@ -237,6 +263,27 @@ class PaymentMethod implements MethodInterface, LivewireMethodInterface
$data['frequency'] = 'Once';
$data['installments'] = 1;
$data['invoice_nums'] = $data['invoices']->pluck('invoice_number')->join(', ');
$data['payment_hash'] = $this->rotessa->payment_hash->hash;
if (count($data['tokens']) === 0) {
$data['authorize_then_redirect'] = true;
$data['contact'] = collect($data['client']->contacts->first()->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'] = GatewayType::ACSS ;
$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();
$this->authorizeView($data);
}
return $data;
}

View File

@ -278,12 +278,12 @@ class RotessaPaymentDriver extends BaseDriver
return $this->company_gateway->getConfigField('testMode') ? 'https://sandbox-api.rotessa.com/v1/' : 'https://api.rotessa.com/v1/';
}
public function processPaymentViewData(array $data)
public function processPaymentViewData(array $data): array
{
return $this->payment_method->paymentData($data);
}
public function livewirePaymentView(array $data)
public function livewirePaymentView(array $data): string
{
return $this->payment_method->livewirePaymentView($data);
}

View File

@ -21,6 +21,7 @@ use App\Models\Invoice;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\Common\MethodInterface;
use App\PaymentDrivers\SquarePaymentDriver;
use App\Utils\Traits\MakesHash;
@ -29,7 +30,7 @@ use Illuminate\Http\Request;
use Illuminate\View\View;
use Square\Http\ApiResponse;
class CreditCard implements MethodInterface
class CreditCard implements MethodInterface, LivewireMethodInterface
{
use MakesHash;
@ -64,10 +65,7 @@ class CreditCard implements MethodInterface
public function paymentView($data)
{
$data['gateway'] = $this->square_driver;
$data['amount'] = $this->square_driver->payment_hash->data->amount_with_fee;
$data['currencyCode'] = $this->square_driver->client->getCurrencyCode();
$data['square_contact'] = $this->buildClientObject();
$data = $this->paymentData($data);
return render('gateways.square.credit_card.pay', $data);
}
@ -238,5 +236,24 @@ class CreditCard implements MethodInterface
return false;
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
return 'gateways.square.credit_card.pay_livewire';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
$data['gateway'] = $this->square_driver;
$data['amount'] = $this->square_driver->payment_hash->data->amount_with_fee;
$data['currencyCode'] = $this->square_driver->client->getCurrencyCode();
$data['square_contact'] = $this->buildClientObject();
return $data;
}
}

View File

@ -24,6 +24,7 @@ use App\Models\Payment;
use App\Models\PaymentHash;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\StripePaymentDriver;
use App\Utils\Traits\MakesHash;
use Exception;
@ -35,7 +36,7 @@ use Stripe\Exception\InvalidRequestException;
use Stripe\Exception\RateLimitException;
use Stripe\PaymentIntent;
class ACH
class ACH implements LivewireMethodInterface
{
use MakesHash;
@ -199,47 +200,7 @@ class ACH
*/
public function paymentView(array $data)
{
$data['gateway'] = $this->stripe;
$data['currency'] = $this->stripe->client->getCurrencyCode();
$data['payment_method_id'] = GatewayType::BANK_TRANSFER;
$data['customer'] = $this->stripe->findOrCreateCustomer();
$data['amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$description = $this->stripe->getDescription(false);
$intent = false;
if (count($data['tokens']) == 1) {
$token = $data['tokens'][0];
$meta = $token->meta;
if(isset($meta->state) && $meta->state == 'unauthorized') {
return redirect()->route('client.payment_methods.show', $token->hashed_id);
}
}
if (count($data['tokens']) == 0) {
$intent =
$this->stripe->createPaymentIntent(
[
'amount' => $data['amount'],
'currency' => $data['currency'],
'setup_future_usage' => 'off_session',
'customer' => $data['customer']->id,
'payment_method_types' => ['us_bank_account'],
'description' => $description,
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::BANK_TRANSFER,
],
'statement_descriptor' => $this->stripe->getStatementDescriptor(),
]
);
}
$data['client_secret'] = $intent ? $intent->client_secret : false;
$data = $this->paymentData($data);
return render('gateways.stripe.ach.pay', $data);
}
@ -628,4 +589,56 @@ class ACH
return $this->stripe->processInternallyFailedPayment($this->stripe, $e);
}
}
public function livewirePaymentView(array $data): string
{
return 'gateways.stripe.ach.pay_livewire';
}
public function paymentData(array $data): array
{
$data['gateway'] = $this->stripe;
$data['currency'] = $this->stripe->client->getCurrencyCode();
$data['payment_method_id'] = GatewayType::BANK_TRANSFER;
$data['customer'] = $this->stripe->findOrCreateCustomer();
$data['amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$description = $this->stripe->getDescription(false);
$intent = false;
if (count($data['tokens']) == 1) {
$token = $data['tokens'][0];
$meta = $token->meta;
if(isset($meta->state) && $meta->state == 'unauthorized') {
return redirect()->route('client.payment_methods.show', $token->hashed_id);
}
}
if (count($data['tokens']) == 0) {
$intent =
$this->stripe->createPaymentIntent(
[
'amount' => $data['amount'],
'currency' => $data['currency'],
'setup_future_usage' => 'off_session',
'customer' => $data['customer']->id,
'payment_method_types' => ['us_bank_account'],
'description' => $description,
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::BANK_TRANSFER,
],
'statement_descriptor' => $this->stripe->getStatementDescriptor(),
]
);
}
$data['client_secret'] = $intent ? $intent->client_secret : false;
return $data;
}
}

View File

@ -12,8 +12,11 @@
namespace App\PaymentDrivers\Stripe;
use App\Http\Controllers\ClientPortal\InvoiceController;
use App\Http\Requests\ClientPortal\Invoices\ProcessInvoicesInBulkRequest;
use App\Models\Payment;
use App\Models\SystemLog;
use Stripe\PaymentIntent;
use App\Models\GatewayType;
use App\Models\PaymentHash;
use App\Models\PaymentType;
@ -26,10 +29,10 @@ use App\Models\ClientGatewayToken;
use Illuminate\Support\Facades\Cache;
use App\Jobs\Mail\PaymentFailureMailer;
use App\PaymentDrivers\StripePaymentDriver;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
use Stripe\PaymentIntent;
class ACSS
class ACSS implements LivewireMethodInterface
{
use MakesHash;
@ -62,7 +65,7 @@ class ACSS
'customer' => $data['customer'],
'payment_method_options' => [
'acss_debit' => [
'currency' => 'cad',
'currency' => strtolower($this->stripe->client->currency()->code),
'mandate_options' => [
'payment_schedule' => 'combined',
'interval_description' => 'On any invoice due date',
@ -92,7 +95,7 @@ class ACSS
$error = "There was a problem setting up this payment method for future use";
if(in_array($setup_intent->type, ["validation_error", "invalid_request_error"])) {
if (in_array($setup_intent->type, ["validation_error", "invalid_request_error"])) {
$error = "Please provide complete payment details.";
}
@ -112,22 +115,24 @@ class ACSS
$client_gateway_token = $this->storePaymentMethod($setup_intent->payment_method, $stripe_setup_intent->mandate, $setup_intent->status == 'succeeded' ? 'authorized' : 'unauthorized');
if($request->has('post_auth_response') && boolval($request->post_auth_response)) {
if ($request->has('post_auth_response') && boolval($request->post_auth_response)) {
/** @var array $data */
$data = Cache::pull($request->post_auth_response);
if(!$data) {
if (!$data) {
throw new PaymentFailed("There was a problem storing this payment method", 500);
}
$hash = PaymentHash::with('fee_invoice')->where('hash', $data['payment_hash'])->first();
$data['tokens'] = [$client_gateway_token];
$data['one_page_checkout'] = (bool) $request->one_page_checkout;
$this->stripe->setPaymentHash($hash);
$this->stripe->setClient($hash->fee_invoice->client);
$this->stripe->setPaymentMethod(GatewayType::ACSS);
return $this->continuePayment($data);
return $this->paymentView($data);
}
return redirect()->route('client.payment_methods.show', $client_gateway_token->hashed_id);
@ -161,73 +166,43 @@ class ACSS
return $intent;
}
/**
* Payment view for ACSS
*
* Determines if any payment tokens are available and if not, generates a mandate
*
* @param array $data
*/
public function paymentView(array $data)
public function paymentData(array $data): array
{
if(count($data['tokens']) == 0) {
$hash = Str::random(32);
Cache::put($hash, $data, 3600);
$data['post_auth_response'] = $hash;
$data['needs_mandate_generate'] = true;
return $this->generateMandate($data);
$data['gateway'] = $this->stripe;
$data['company_gateway'] = $this->stripe->company_gateway;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$intent = \Stripe\SetupIntent::create([
'usage' => 'off_session',
'payment_method_types' => ['acss_debit'],
'customer' => $data['customer'],
'payment_method_options' => [
'acss_debit' => [
'currency' => strtolower($this->stripe->client->currency()->code),
'mandate_options' => [
'payment_schedule' => 'combined',
'interval_description' => 'On any invoice due date',
'transaction_type' => 'personal',
],
'verification_method' => 'instant',
],
],
], $this->stripe->stripe_connect_auth);
$data['pi_client_secret'] = $intent->client_secret;
return $data;
}
return $this->continuePayment($data);
}
/**
* Generate a payment Mandate for ACSS
*
* @param array $data
*/
private function generateMandate(array $data)
{
$data['gateway'] = $this->stripe;
$data['company_gateway'] = $this->stripe->company_gateway;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$intent = \Stripe\SetupIntent::create([
'usage' => 'off_session',
'payment_method_types' => ['acss_debit'],
'customer' => $data['customer'],
'payment_method_options' => [
'acss_debit' => [
'currency' => 'cad',
'mandate_options' => [
'payment_schedule' => 'combined',
'interval_description' => 'On any invoice due date',
'transaction_type' => 'personal',
],
'verification_method' => 'instant',
],
],
], $this->stripe->stripe_connect_auth);
$data['pi_client_secret'] = $intent->client_secret;
return render('gateways.stripe.acss.authorize', array_merge($data));
}
/**
* Continues the payment flow after a Mandate has been successfully generated
*
* @param array $data
*/
private function continuePayment(array $data)
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
@ -240,6 +215,39 @@ class ACSS
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
return $data;
}
/**
* Payment view for ACSS
*
* Determines if any payment tokens are available and if not, generates a mandate
*
* @param array $data
*/
public function paymentView(array $data)
{
$data = $this->paymentData($data);
if (isset($data['one_page_checkout']) && $data['one_page_checkout']) {
$data = [
'invoices' => collect($data['invoices'])->map(fn ($invoice) => $invoice['invoice_id'])->toArray(),
'action' => 'payment',
];
$request = new ProcessInvoicesInBulkRequest();
$request->replace($data);
session()->flash('message', ctrans('texts.payment_method_added'));
return app(InvoiceController::class)->bulk($request);
}
if (array_key_exists('needs_mandate_generate', $data)) {
return render('gateways.stripe.acss.authorize', array_merge($data));
}
return render('gateways.stripe.acss.pay', $data);
}
@ -267,7 +275,6 @@ class ACSS
$gateway_response = json_decode($request->gateway_response);
/** @var \App\Models\ClientGatewayToken $cgt */
$cgt = ClientGatewayToken::find($this->decodePrimaryKey($request->token));
/** @var \Stripe\PaymentIntent $intent */
@ -400,4 +407,13 @@ class ACSS
return $this->stripe->processInternallyFailedPayment($this->stripe, $e);
}
}
public function livewirePaymentView(array $data): string
{
if (array_key_exists('needs_mandate_generate', $data)) {
return 'gateways.stripe.acss.authorize_livewire';
}
return 'gateways.stripe.acss.pay_livewire';
}
}

View File

@ -12,16 +12,19 @@
namespace App\PaymentDrivers\Stripe;
use App\Exceptions\PaymentFailed;
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
use App\Jobs\Util\SystemLogger;
use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\Models\GatewayType;
use App\Models\PaymentType;
use App\Jobs\Util\SystemLogger;
use App\Exceptions\PaymentFailed;
use App\PaymentDrivers\StripePaymentDriver;
use Stripe\Exception\InvalidRequestException;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
use Throwable;
class Alipay
class Alipay implements LivewireMethodInterface
{
/** @var StripePaymentDriver */
public $stripe;
@ -33,26 +36,9 @@ class Alipay
public function paymentView(array $data)
{
$intent = \Stripe\PaymentIntent::create([
'amount' => $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency()),
'currency' => $this->stripe->client->currency()->code,
'payment_method_types' => ['alipay'],
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::ALIPAY,
],
], $this->stripe->stripe_connect_auth);
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['ci_intent'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency())]);
$this->stripe->payment_hash->save();
$data = $this->paymentData($data);
return render('gateways.stripe.alipay.pay', $data);
}
@ -81,8 +67,6 @@ class Alipay
$this->stripe->stripe_connect_auth
);
nlog($pi);
if (in_array($pi->status, ['succeeded', 'pending'])) {
return $this->processSuccesfulRedirect($pi);
}
@ -146,4 +130,46 @@ class Alipay
throw new PaymentFailed('Failed to process the payment.', 500);
}
/**
* @inheritDoc
*/
public function livewirePaymentView(array $data): string
{
return 'gateways.stripe.alipay.pay_livewire';
}
/**
* @inheritDoc
*/
public function paymentData(array $data): array
{
try {
$intent = \Stripe\PaymentIntent::create([
'amount' => $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency()),
'currency' => $this->stripe->client->currency()->code,
'payment_method_types' => ['alipay'],
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::ALIPAY,
],
], $this->stripe->stripe_connect_auth);
}
catch(\Throwable $e){
throw new PaymentFailed($e->getMessage(), $e->getCode());
}
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['ci_intent'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency())]);
$this->stripe->payment_hash->save();
return $data;
}
}

View File

@ -20,12 +20,13 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\Stripe\Jobs\UpdateCustomer;
use App\PaymentDrivers\StripePaymentDriver;
use App\Utils\Number;
use Stripe\Checkout\Session;
class BACS
class BACS implements LivewireMethodInterface
{
public $stripe;
@ -69,9 +70,7 @@ class BACS
}
public function paymentView(array $data)
{
$data['gateway'] = $this->stripe;
$data['amount'] = $data['total']['amount_with_fee'];
$data['payment_hash'] = $this->stripe->payment_hash->hash;
$data = $this->paymentData($data);
return render('gateways.stripe.bacs.pay', $data);
}
@ -187,4 +186,18 @@ class BACS
return $this->stripe->processInternallyFailedPayment($this->stripe, $e);
}
}
public function paymentData(array $data): array
{
$data['gateway'] = $this->stripe;
$data['amount'] = $data['total']['amount_with_fee'];
$data['payment_hash'] = $this->stripe->payment_hash->hash;
return $data;
}
public function livewirePaymentView(array $data): string
{
return 'gateways.stripe.bacs.pay_livewire';
}
}

View File

@ -19,9 +19,10 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\StripePaymentDriver;
class BECS
class BECS implements LivewireMethodInterface
{
/** @var StripePaymentDriver */
public StripePaymentDriver $stripe;
@ -39,33 +40,7 @@ class BECS
public function paymentView(array $data)
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
$data['payment_method_id'] = GatewayType::BECS;
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$data['payment_hash'] = $this->stripe->payment_hash->hash;
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
'currency' => $this->stripe->client->currency()->code,
'payment_method_types' => ['au_becs_debit'],
'setup_future_usage' => 'off_session',
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::BECS,
],
], array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
$data = $this->paymentData($data);
return render('gateways.stripe.becs.pay', $data);
}
@ -161,4 +136,42 @@ class BECS
return $this->stripe->processInternallyFailedPayment($this->stripe, $e);
}
}
public function paymentData(array $data): array
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
$data['payment_method_id'] = GatewayType::BECS;
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$data['payment_hash'] = $this->stripe->payment_hash->hash;
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
'currency' => $this->stripe->client->currency()->code,
'payment_method_types' => ['au_becs_debit'],
'setup_future_usage' => 'off_session',
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::BECS,
],
], array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
return $data;
}
public function livewirePaymentView(array $data): string
{
return 'gateways.stripe.becs.pay_livewire';
}
}

View File

@ -18,9 +18,10 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\StripePaymentDriver;
class Bancontact
class Bancontact implements LivewireMethodInterface
{
/** @var StripePaymentDriver */
public StripePaymentDriver $stripe;
@ -37,32 +38,8 @@ class Bancontact
public function paymentView(array $data)
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
'currency' => 'eur',
'payment_method_types' => ['bancontact'],
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::BANCONTACT,
],
], array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
$data = $this->paymentData($data);
$data = $this->paymentData($data);
return render('gateways.stripe.bancontact.pay', $data);
}
@ -93,8 +70,8 @@ class Bancontact
/* @todo: https://github.com/invoiceninja/invoiceninja/pull/3789/files#r436175798 */
//catch duplicate submissions.
if (Payment::where('transaction_reference', $payment_intent)->exists()) {
return redirect()->route('client.payments.index');
if ($payment = Payment::query()->where('transaction_reference', $payment_intent)->first()) {
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
}
$this->stripe->init();
@ -107,7 +84,7 @@ class Bancontact
'gateway_type_id' => GatewayType::BANCONTACT,
];
$this->stripe->createPayment($data, Payment::STATUS_PENDING);
$payment = $this->stripe->createPayment($data, Payment::STATUS_PENDING);
SystemLogger::dispatch(
['response' => $this->stripe->payment_hash->data, 'data' => $data],
@ -118,7 +95,8 @@ class Bancontact
$this->stripe->client->company,
);
return redirect()->route('client.payments.index');
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
}
public function processUnsuccessfulPayment()
@ -143,4 +121,41 @@ class Bancontact
throw new PaymentFailed('Failed to process the payment.', 500);
}
public function paymentData(array $data): array
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
'currency' => 'eur',
'payment_method_types' => ['bancontact'],
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::BANCONTACT,
],
], array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
return $data;
}
public function livewirePaymentView(array $data): string
{
return 'gateways.stripe.bancontact.pay_livewire';
}
}

View File

@ -19,12 +19,13 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\StripePaymentDriver;
use App\Utils\Number;
use App\Utils\Traits\MakesHash;
use Stripe\PaymentIntent;
class BankTransfer
class BankTransfer implements LivewireMethodInterface
{
use MakesHash;
@ -38,37 +39,8 @@ class BankTransfer
public function paymentView(array $data)
{
$this->stripe->init();
$intent = \Stripe\PaymentIntent::create([
'amount' => $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency()),
'currency' => $this->stripe->client->currency()->code,
'customer' => $this->stripe->findOrCreateCustomer()->id,
'description' => $this->stripe->getDescription(false),
'payment_method_types' => ['customer_balance'],
'payment_method_data' => [
'type' => 'customer_balance',
],
'payment_method_options' => [
'customer_balance' => [
'funding_type' => 'bank_transfer',
'bank_transfer' => $this->resolveBankType()
],
],
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::DIRECT_DEBIT,
],
], $this->stripe->stripe_connect_auth);
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency())]);
$this->stripe->payment_hash->save();
$data = [];
$data['return_url'] = $this->buildReturnUrl();
$data['gateway'] = $this->stripe;
$data['client_secret'] = $intent ? $intent->client_secret : false;
$data = $this->paymentData($data);
$data = $this->paymentData($data);
return render('gateways.stripe.bank_transfer.pay', $data);
}
@ -317,4 +289,46 @@ class BankTransfer
throw new PaymentFailed('Failed to process the payment.', 500);
}
}
public function paymentData(array $data): array
{
$this->stripe->init();
$intent = \Stripe\PaymentIntent::create([
'amount' => $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency()),
'currency' => $this->stripe->client->currency()->code,
'customer' => $this->stripe->findOrCreateCustomer()->id,
'description' => $this->stripe->getDescription(false),
'payment_method_types' => ['customer_balance'],
'payment_method_data' => [
'type' => 'customer_balance',
],
'payment_method_options' => [
'customer_balance' => [
'funding_type' => 'bank_transfer',
'bank_transfer' => $this->resolveBankType()
],
],
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::DIRECT_DEBIT,
],
], $this->stripe->stripe_connect_auth);
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency())]);
$this->stripe->payment_hash->save();
$data = [];
$data['return_url'] = $this->buildReturnUrl();
$data['gateway'] = $this->stripe;
$data['client_secret'] = $intent ? $intent->client_secret : false;
return $data;
}
public function livewirePaymentView(array $data): string
{
return 'gateways.stripe.bank_transfer.pay_livewire';
}
}

View File

@ -19,6 +19,7 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\Common\MethodInterface;
use App\PaymentDrivers\StripePaymentDriver;
use App\Utils\Ninja;
@ -29,7 +30,7 @@ use Stripe\ApplePayDomain;
use Stripe\Exception\ApiErrorException;
use Stripe\PaymentIntent;
class BrowserPay implements MethodInterface
class BrowserPay implements MethodInterface, LivewireMethodInterface
{
protected StripePaymentDriver $stripe;
@ -64,7 +65,8 @@ class BrowserPay implements MethodInterface
return redirect()->route('client.payment_methods.index');
}
public function paymentView(array $data): View
public function paymentData(array $data): array
{
$payment_intent_data = [
'amount' => $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency()),
@ -93,6 +95,13 @@ class BrowserPay implements MethodInterface
'requestPayerEmail' => true,
];
return $data;
}
public function paymentView(array $data): View
{
$data = $this->paymentData($data);
return render('gateways.stripe.browser_pay.pay', $data);
}
@ -153,7 +162,7 @@ class BrowserPay implements MethodInterface
$this->stripe->client->company,
);
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
return redirect()->route('client.payments.show', ['payment' => $this->stripe->encodePrimaryKey($payment->id)]);
}
/**
@ -231,4 +240,9 @@ class BrowserPay implements MethodInterface
return str_replace(['https://', '/public'], '', $domain);
}
public function livewirePaymentView(array $data): string
{
return 'gateways.stripe.browser_pay.pay_livewire';
}
}

View File

@ -50,7 +50,7 @@ class Charge
{
if ($cgt->gateway_type_id == GatewayType::BANK_TRANSFER) {
return (new ACH($this->stripe))->tokenBilling($cgt, $payment_hash);
} elseif($cgt->gateway_type_id == GatewayType::ACSS) {
} elseif ($cgt->gateway_type_id == GatewayType::ACSS) {
return (new ACSS($this->stripe))->tokenBilling($cgt, $payment_hash);
}
@ -82,6 +82,9 @@ class Charge
if ($cgt->gateway_type_id == GatewayType::BACS) {
$data['payment_method_types'] = ['bacs_debit'];
}
if ($cgt->gateway_type_id == GatewayType::CREDIT_CARD) {
$data['payment_method_types'] = ["card","link"];
}
/* Should improve token billing with client not present */
if (!auth()->guard('contact')->check()) {

View File

@ -19,12 +19,13 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\Stripe\Jobs\UpdateCustomer;
use App\PaymentDrivers\StripePaymentDriver;
use Stripe\PaymentIntent;
use Stripe\PaymentMethod;
class CreditCard
class CreditCard implements LivewireMethodInterface
{
public $stripe;
@ -57,7 +58,7 @@ class CreditCard
return redirect()->route('client.payment_methods.index');
}
public function paymentView(array $data)
public function paymentData(array $data): array
{
$description = $this->stripe->getDescription(false);
@ -77,9 +78,21 @@ class CreditCard
$data['intent'] = $this->stripe->createPaymentIntent($payment_intent_data);
$data['gateway'] = $this->stripe;
return $data;
}
public function paymentView(array $data)
{
$data = $this->paymentData($data);
return render('gateways.stripe.credit_card.pay', $data);
}
public function livewirePaymentView(array $data): string
{
return 'gateways.stripe.credit_card.pay_livewire';
}
public function paymentResponse(PaymentResponseRequest $request)
{
$this->stripe->init();

View File

@ -18,9 +18,10 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\StripePaymentDriver;
class EPS
class EPS implements LivewireMethodInterface
{
/** @var StripePaymentDriver */
public StripePaymentDriver $stripe;
@ -37,31 +38,7 @@ class EPS
public function paymentView(array $data)
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
'currency' => 'eur',
'payment_method_types' => ['eps'],
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::EPS,
],
], array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
$data = $this->paymentData($data);
return render('gateways.stripe.eps.pay', $data);
}
@ -94,8 +71,9 @@ class EPS
$this->stripe->init();
//catch duplicate submissions.
if (Payment::where('transaction_reference', $payment_intent)->exists()) {
return redirect()->route('client.payments.index');
if ($payment = Payment::query()->where('transaction_reference', $payment_intent)->first()) {
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
}
$data = [
@ -106,7 +84,7 @@ class EPS
'gateway_type_id' => GatewayType::EPS,
];
$this->stripe->createPayment($data, Payment::STATUS_PENDING);
$payment = $this->stripe->createPayment($data, Payment::STATUS_PENDING);
SystemLogger::dispatch(
['response' => $this->stripe->payment_hash->data, 'data' => $data],
@ -117,7 +95,8 @@ class EPS
$this->stripe->client->company,
);
return redirect()->route('client.payments.index');
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
}
public function processUnsuccessfulPayment()
@ -142,4 +121,40 @@ class EPS
throw new PaymentFailed('Failed to process the payment.', 500);
}
public function paymentData(array $data): array
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
'currency' => 'eur',
'payment_method_types' => ['eps'],
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::EPS,
],
], array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
return $data;
}
public function livewirePaymentView(array $data): string
{
return 'gateways.stripe.eps.pay_livewire';
}
}

View File

@ -19,9 +19,10 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\StripePaymentDriver;
class FPX
class FPX implements LivewireMethodInterface
{
/** @var StripePaymentDriver */
public StripePaymentDriver $stripe;
@ -38,31 +39,7 @@ class FPX
public function paymentView(array $data)
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
'currency' => $this->stripe->client->getCurrencyCode(),
'payment_method_types' => ['fpx'],
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::FPX,
],
], array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
$data = $this->paymentData($data);
return render('gateways.stripe.fpx.pay', $data);
}
@ -102,7 +79,7 @@ class FPX
'gateway_type_id' => GatewayType::FPX,
];
$this->stripe->createPayment($data, Payment::STATUS_PENDING);
$payment = $this->stripe->createPayment($data, Payment::STATUS_PENDING);
SystemLogger::dispatch(
['response' => $this->stripe->payment_hash->data, 'data' => $data],
@ -112,8 +89,9 @@ class FPX
$this->stripe->client,
$this->stripe->client->company,
);
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
return redirect()->route('client.payments.index');
}
public function processUnsuccessfulPayment()
@ -143,4 +121,40 @@ class FPX
throw new PaymentFailed('Failed to process the payment.', 400);
}
public function paymentData(array $data): array
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
'currency' => $this->stripe->client->getCurrencyCode(),
'payment_method_types' => ['fpx'],
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::FPX,
],
], array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
return $data;
}
public function livewirePaymentView(array $data): string
{
return 'gateways.stripe.fpx.pay_livewire';
}
}

View File

@ -18,9 +18,10 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\StripePaymentDriver;
class GIROPAY
class GIROPAY implements LivewireMethodInterface
{
/** @var StripePaymentDriver */
public StripePaymentDriver $stripe;
@ -37,31 +38,7 @@ class GIROPAY
public function paymentView(array $data)
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
'currency' => 'eur',
'payment_method_types' => ['giropay'],
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::GIROPAY,
],
], array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
$data = $this->paymentData($data);
return render('gateways.stripe.giropay.pay', $data);
}
@ -94,8 +71,8 @@ class GIROPAY
$this->stripe->init();
//catch duplicate submissions.
if (Payment::where('transaction_reference', $payment_intent)->exists()) {
return redirect()->route('client.payments.index');
if ($payment = Payment::query()->where('transaction_reference', $payment_intent)->first()) {
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
}
$data = [
@ -106,7 +83,7 @@ class GIROPAY
'gateway_type_id' => GatewayType::GIROPAY,
];
$this->stripe->createPayment($data, Payment::STATUS_PENDING);
$payment = $this->stripe->createPayment($data, Payment::STATUS_PENDING);
SystemLogger::dispatch(
['response' => $this->stripe->payment_hash->data, 'data' => $data],
@ -117,7 +94,7 @@ class GIROPAY
$this->stripe->client->company,
);
return redirect()->route('client.payments.index');
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
}
public function processUnsuccessfulPayment()
@ -142,4 +119,40 @@ class GIROPAY
throw new PaymentFailed('Failed to process the payment.', 500);
}
public function paymentData(array $data): array
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
'currency' => 'eur',
'payment_method_types' => ['giropay'],
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::GIROPAY,
],
], array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
return $data;
}
public function livewirePaymentView(array $data): string
{
return 'gateways.stripe.giropay.pay_livewire';
}
}

View File

@ -18,9 +18,10 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\StripePaymentDriver;
class Klarna
class Klarna implements LivewireMethodInterface
{
/** @var StripePaymentDriver */
public StripePaymentDriver $stripe;
@ -37,33 +38,7 @@ class Klarna
public function paymentView(array $data)
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$description = $this->stripe->getDescription(false);
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
'currency' => $this->stripe->client->getCurrencyCode(),
'payment_method_types' => ['klarna'],
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $description,
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::KLARNA,
],
], array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
$data = $this->paymentData($data);
return render('gateways.stripe.klarna.pay', $data);
}
@ -94,8 +69,10 @@ class Klarna
$this->stripe->init();
//catch duplicate submissions.
if (Payment::where('transaction_reference', $payment_intent)->exists()) {
return redirect()->route('client.payments.index');
if ($pay_exists = Payment::query()->where('transaction_reference', $payment_intent)->first()) {
return redirect()->route('client.payments.show', ['payment' => $pay_exists->hashed_id]);
}
$data = [
@ -106,7 +83,7 @@ class Klarna
'gateway_type_id' => GatewayType::KLARNA,
];
$this->stripe->createPayment($data, Payment::STATUS_PENDING);
$payment = $this->stripe->createPayment($data, Payment::STATUS_PENDING);
SystemLogger::dispatch(
['response' => $this->stripe->payment_hash->data, 'data' => $data],
@ -117,7 +94,7 @@ class Klarna
$this->stripe->client->company,
);
return redirect()->route('client.payments.index');
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
}
public function processUnsuccessfulPayment()
@ -142,4 +119,42 @@ class Klarna
throw new PaymentFailed(ctrans('texts.gateway_error'), 500);
}
public function paymentData(array $data): array
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$description = $this->stripe->getDescription(false);
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
'currency' => $this->stripe->client->getCurrencyCode(),
'payment_method_types' => ['klarna'],
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $description,
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::KLARNA,
],
], array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
return $data;
}
public function livewirePaymentView(array $data): string
{
return 'gateways.stripe.klarna.pay_livewire';
}
}

View File

@ -18,9 +18,10 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\StripePaymentDriver;
class PRZELEWY24
class PRZELEWY24 implements LivewireMethodInterface
{
/** @var StripePaymentDriver */
public StripePaymentDriver $stripe;
@ -37,31 +38,7 @@ class PRZELEWY24
public function paymentView(array $data)
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
'currency' => 'eur',
'payment_method_types' => ['p24'],
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::PRZELEWY24,
],
], array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
$data = $this->paymentData($data);
return render('gateways.stripe.przelewy24.pay', $data);
}
@ -94,8 +71,8 @@ class PRZELEWY24
$this->stripe->init();
//catch duplicate submissions.
if (Payment::where('transaction_reference', $payment_intent)->exists()) {
return redirect()->route('client.payments.index');
if ($pay_exists = Payment::query()->where('transaction_reference', $payment_intent)->first()) {
return redirect()->route('client.payments.show', ['payment' => $pay_exists->hashed_id]);
}
$data = [
@ -106,7 +83,7 @@ class PRZELEWY24
'gateway_type_id' => GatewayType::PRZELEWY24,
];
$this->stripe->createPayment($data, Payment::STATUS_PENDING);
$payment = $this->stripe->createPayment($data, Payment::STATUS_PENDING);
SystemLogger::dispatch(
['response' => $this->stripe->payment_hash->data, 'data' => $data],
@ -117,7 +94,8 @@ class PRZELEWY24
$this->stripe->client->company,
);
return redirect()->route('client.payments.index');
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
}
public function processUnsuccessfulPayment()
@ -142,4 +120,40 @@ class PRZELEWY24
throw new PaymentFailed('Failed to process the payment.', 500);
}
public function paymentData(array $data): array
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
'currency' => 'eur',
'payment_method_types' => ['p24'],
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::PRZELEWY24,
],
], array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
return $data;
}
public function livewirePaymentView(array $data): string
{
return 'gateways.stripe.przelewy24.pay_livewire';
}
}

View File

@ -19,9 +19,10 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\StripePaymentDriver;
class SEPA
class SEPA implements LivewireMethodInterface
{
/** @var StripePaymentDriver */
public StripePaymentDriver $stripe;
@ -47,33 +48,7 @@ class SEPA
public function paymentView(array $data)
{
$data['gateway'] = $this->stripe;
$data['payment_method_id'] = GatewayType::SEPA;
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$data['payment_hash'] = $this->stripe->payment_hash->hash;
$intent_data = [
'amount' => $data['stripe_amount'],
'currency' => 'eur',
'payment_method_types' => ['sepa_debit'],
'setup_future_usage' => 'off_session',
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::SEPA,
],
];
$intent = \Stripe\PaymentIntent::create($intent_data, array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
$data = $this->paymentData($data);
return render('gateways.stripe.sepa.pay', $data);
}
@ -167,7 +142,7 @@ class SEPA
'company_id' => $this->stripe->client->company_id,
])->first();
if($token) {
if ($token) {
return $token;
}
@ -176,4 +151,58 @@ class SEPA
return $this->stripe->processInternallyFailedPayment($this->stripe, $e);
}
}
public function paymentData(array $data): array
{
$data['gateway'] = $this->stripe;
$data['payment_method_id'] = GatewayType::SEPA;
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$data['payment_hash'] = $this->stripe->payment_hash->hash;
/** if the iban and client country don't match (OR UK IBAN) - need to inject billing details also */
// $data['billing_details'] = [
// 'name' => $this->stripe->client->present()->name(),
// 'email' => $this->stripe->client->present()->email(),
// 'address' => [
// 'line1' => $this->stripe->client->address1 ?? '',
// 'line2' => $this->stripe->client->address2 ?? '',
// 'city' => $this->stripe->client->city ?? '',
// 'state' => $this->stripe->client->state ?? '',
// 'postal_code' => $this->stripe->client->postal_code ?? '',
// 'country' => $this->stripe->client->country->iso_3166_2 ?? 'DE',
// ]
// ];
$intent_data = [
'amount' => $data['stripe_amount'],
'currency' => 'eur',
'payment_method_types' => ['sepa_debit'],
'setup_future_usage' => 'off_session',
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::SEPA,
],
];
$intent = \Stripe\PaymentIntent::create($intent_data, array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
return $data;
}
public function livewirePaymentView(array $data): string
{
return 'gateways.stripe.sepa.pay_livewire';
}
}

View File

@ -18,9 +18,10 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\StripePaymentDriver;
class SOFORT
class SOFORT implements LivewireMethodInterface
{
/** @var StripePaymentDriver */
public StripePaymentDriver $stripe;
@ -37,31 +38,8 @@ class SOFORT
public function paymentView(array $data)
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
'currency' => 'eur',
'payment_method_types' => ['sofort'],
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::SOFORT,
],
], array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
$data = $this->paymentData($data);
$data = $this->paymentData($data);
return render('gateways.stripe.sofort.pay', $data);
}
@ -101,7 +79,7 @@ class SOFORT
'gateway_type_id' => GatewayType::SOFORT,
];
$this->stripe->createPayment($data, Payment::STATUS_PENDING);
$payment = $this->stripe->createPayment($data, Payment::STATUS_PENDING);
SystemLogger::dispatch(
['response' => $this->stripe->payment_hash->data, 'data' => $data],
@ -112,7 +90,7 @@ class SOFORT
$this->stripe->client->company,
);
return redirect()->route('client.payments.index');
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
}
public function processUnsuccessfulPayment()
@ -137,4 +115,40 @@ class SOFORT
throw new PaymentFailed('Failed to process the payment.', 500);
}
public function paymentData(array $data): array
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
'currency' => 'eur',
'payment_method_types' => ['sofort'],
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::SOFORT,
],
], array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
return $data;
}
public function livewirePaymentView(array $data): string
{
return 'gateways.stripe.sofort.pay_livewire';
}
}

View File

@ -18,9 +18,10 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\StripePaymentDriver;
class iDeal
class iDeal implements LivewireMethodInterface
{
/** @var StripePaymentDriver */
public StripePaymentDriver $stripe;
@ -37,31 +38,7 @@ class iDeal
public function paymentView(array $data)
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
'currency' => 'eur',
'payment_method_types' => ['ideal'],
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::IDEAL,
],
], array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
$data = $this->paymentData($data);
return render('gateways.stripe.ideal.pay', $data);
}
@ -94,8 +71,8 @@ class iDeal
$this->stripe->init();
//catch duplicate submissions.
if (Payment::where('transaction_reference', $payment_intent)->exists()) {
return redirect()->route('client.payments.index');
if ($pay_exists = Payment::query()->where('transaction_reference', $payment_intent)->first()) {
return redirect()->route('client.payments.show', ['payment' => $pay_exists->hashed_id]);
}
$data = [
@ -106,7 +83,7 @@ class iDeal
'gateway_type_id' => GatewayType::IDEAL,
];
$this->stripe->createPayment($data, Payment::STATUS_COMPLETED);
$payment = $this->stripe->createPayment($data, Payment::STATUS_COMPLETED);
SystemLogger::dispatch(
['response' => $this->stripe->payment_hash->data, 'data' => $data],
@ -117,7 +94,7 @@ class iDeal
$this->stripe->client->company,
);
return redirect()->route('client.payments.index');
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
}
public function processUnsuccessfulPayment()
@ -142,4 +119,40 @@ class iDeal
throw new PaymentFailed('Failed to process the payment.', 500);
}
public function paymentData(array $data): array
{
$this->stripe->init();
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
$data['client'] = $this->stripe->client;
$data['customer'] = $this->stripe->findOrCreateCustomer()->id;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
'currency' => 'eur',
'payment_method_types' => ['ideal'],
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->getDescription(false),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::IDEAL,
],
], array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
$data['pi_client_secret'] = $intent->client_secret;
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
$this->stripe->payment_hash->save();
return $data;
}
public function livewirePaymentView(array $data): string
{
return 'gateways.stripe.ideal.pay_livewire';
}
}

View File

@ -126,8 +126,8 @@ class StripePaymentDriver extends BaseDriver
);
Stripe::setApiKey($this->company_gateway->getConfigField('apiKey'));
Stripe::setApiVersion('2022-11-15');
// Stripe::setAPiVersion('2023-08-16');
// Stripe::setApiVersion('2022-11-15');
Stripe::setAPiVersion('2023-08-16');
}
return $this;
@ -419,6 +419,33 @@ class StripePaymentDriver extends BaseDriver
return $this->payment_method->paymentView($data);
}
public function processPaymentViewData(array $data): array
{
$data = $this->payment_method->paymentData($data);
$data['stripe_account_id'] = $this->company_gateway->getConfigField('account_id');
if (array_key_exists('intent', $data)) {
$data['client_secret'] = $data['intent']->client_secret;
}
unset($data['intent']);
$token_billing_string = 'true';
if($this->company_gateway->token_billing == 'off' || $this->company_gateway->token_billing == 'optin') {
$token_billing_string = 'false';
}
if (isset($data['pre_payment']) && $data['pre_payment'] == '1' && isset($data['is_recurring']) && $data['is_recurring'] == '1') {
$token_billing_string = 'true';
}
$data['token_billing_string'] = $token_billing_string;
return $data;
}
public function processPaymentResponse($request)
{
return $this->payment_method->paymentResponse($request);
@ -1021,4 +1048,6 @@ class StripePaymentDriver extends BaseDriver
return false;
}
}

View File

@ -326,7 +326,7 @@ class BaseRepository
try{
$model->service()->getEInvoice();
}
catch(\Exception $e){
catch(\Throwable $e){
nlog("EXCEPTION:: BASEREPOSITORY:: Error generating e_invoice for model {$model->id}");
nlog($e->getMessage());
}

View File

@ -76,13 +76,6 @@ class ClientRepository extends BaseRepository
$client->country_id = $company->settings->country_id;
}
if(isset($data['e_invoice']) && is_array($data['e_invoice'])) {
//ensure it is normalized first!
$data['e_invoice'] = $client->arrayFilterRecursive($data['e_invoice']);
$client->e_invoice = $data['e_invoice'];
}
$client->save();
if (! isset($client->number) || empty($client->number) || strlen($client->number) == 0) {

View File

@ -57,11 +57,8 @@ class CompanyRepository extends BaseRepository
if(isset($data['smtp_password'])) {
$company->smtp_password = $data['smtp_password'];
}
if(isset($data['e_invoice']) && is_array($data['e_invoice'])){
//ensure it is normalized first!
$data['e_invoice'] = $company->arrayFilterRecursive($data['e_invoice']);
if (isset($data['e_invoice'])) {
$company->e_invoice = $data['e_invoice'];
}

Some files were not shown because too many files have changed in this diff Show More