mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-03 23:07:32 -05:00 
			
		
		
		
	GoCardless: New payment flow (#72)
* pass livewirePaymentView & processPaymentView thru base driver * gocardless
This commit is contained in:
		
							parent
							
								
									6aefbbf2c6
								
							
						
					
					
						commit
						4e608eb242
					
				@ -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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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\GoCardlessPaymentDriver;
 | 
			
		||||
use App\Utils\Traits\MakesHash;
 | 
			
		||||
@ -29,7 +30,7 @@ use Illuminate\Http\Request;
 | 
			
		||||
use Illuminate\Routing\Redirector;
 | 
			
		||||
use Illuminate\View\View;
 | 
			
		||||
 | 
			
		||||
class DirectDebit implements MethodInterface
 | 
			
		||||
class DirectDebit implements MethodInterface, LivewireMethodInterface
 | 
			
		||||
{
 | 
			
		||||
    use MakesHash;
 | 
			
		||||
 | 
			
		||||
@ -218,9 +219,7 @@ class DirectDebit 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.direct_debit.pay', $data);
 | 
			
		||||
    }
 | 
			
		||||
@ -330,4 +329,24 @@ 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();
 | 
			
		||||
 | 
			
		||||
        return $data;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -194,9 +195,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);
 | 
			
		||||
 | 
			
		||||
@ -221,4 +221,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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
@ -29,7 +30,7 @@ use Illuminate\Http\Request;
 | 
			
		||||
use Illuminate\Routing\Redirector;
 | 
			
		||||
use Illuminate\View\View;
 | 
			
		||||
 | 
			
		||||
class SEPA implements MethodInterface
 | 
			
		||||
class SEPA implements MethodInterface, LivewireMethodInterface
 | 
			
		||||
{
 | 
			
		||||
    use MakesHash;
 | 
			
		||||
 | 
			
		||||
@ -145,9 +146,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 +256,24 @@ 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();
 | 
			
		||||
 | 
			
		||||
        return $data;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,56 @@
 | 
			
		||||
<div class="rounded-lg border bg-card text-card-foreground shadow-sm overflow-hidden py-5 bg-white sm:gap-4" id="gocardless-ach-payment">
 | 
			
		||||
@if (count($tokens) > 0)
 | 
			
		||||
        <div class="alert alert-failure mb-4" hidden id="errors"></div>
 | 
			
		||||
 | 
			
		||||
        @include('portal.ninja2020.gateways.includes.payment_details')
 | 
			
		||||
 | 
			
		||||
        <form action="{{ route('client.payments.response') }}" method="post" id="server-response">
 | 
			
		||||
            @csrf
 | 
			
		||||
            <input type="hidden" name="company_gateway_id" value="{{ $gateway->getCompanyGatewayId() }}">
 | 
			
		||||
            <input type="hidden" name="payment_method_id" value="{{ $payment_method_id }}">
 | 
			
		||||
            <input type="hidden" name="source" value="">
 | 
			
		||||
            <input type="hidden" name="amount" value="{{ $amount }}">
 | 
			
		||||
            <input type="hidden" name="currency" value="{{ $currency }}">
 | 
			
		||||
            <input type="hidden" name="payment_hash" value="{{ $payment_hash }}">
 | 
			
		||||
        </form>
 | 
			
		||||
 | 
			
		||||
        @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')])
 | 
			
		||||
            @if (count($tokens) > 0)
 | 
			
		||||
                @foreach ($tokens as $token)
 | 
			
		||||
                    <label class="mr-4">
 | 
			
		||||
                        <input type="radio" data-token="{{ $token->token }}" name="payment-type"
 | 
			
		||||
                            class="form-radio cursor-pointer toggle-payment-with-token" />
 | 
			
		||||
                        <span class="ml-1 cursor-pointer">{{ ctrans('texts.bank_transfer') }}
 | 
			
		||||
                            (#{{ $token->token }})</span>
 | 
			
		||||
                    </label>
 | 
			
		||||
                @endforeach
 | 
			
		||||
            @endisset
 | 
			
		||||
        @endcomponent
 | 
			
		||||
 | 
			
		||||
    @else
 | 
			
		||||
        @component('portal.ninja2020.components.general.card-element-single', ['title' => 'ACH', 'show_title' => false])
 | 
			
		||||
            <span>{{ ctrans('texts.bank_account_not_linked') }}</span>
 | 
			
		||||
            <a class="button button-link text-primary"
 | 
			
		||||
                href="{{ route('client.payment_methods.index') }}">{{ ctrans('texts.add_payment_method') }}</a>
 | 
			
		||||
        @endcomponent
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    @if (count($tokens) > 0)
 | 
			
		||||
        @include('portal.ninja2020.gateways.includes.pay_now')
 | 
			
		||||
    @endif
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@script
 | 
			
		||||
    <script>
 | 
			
		||||
        Array
 | 
			
		||||
            .from(document.getElementsByClassName('toggle-payment-with-token'))
 | 
			
		||||
            .forEach((element) => element.addEventListener('click', (element) => {
 | 
			
		||||
                document.querySelector('input[name=source]').value = element.target.dataset.token;
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
        document.getElementById('pay-now').addEventListener('click', function() {
 | 
			
		||||
            document.getElementById('server-response').submit();
 | 
			
		||||
        });
 | 
			
		||||
    </script>
 | 
			
		||||
@endscript
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,56 @@
 | 
			
		||||
<div class="rounded-lg border bg-card text-card-foreground shadow-sm overflow-hidden py-5 bg-white sm:gap-4" id="gocardless-direct-debit-payment">
 | 
			
		||||
@if (count($tokens) > 0)
 | 
			
		||||
        <div class="alert alert-failure mb-4" hidden id="errors"></div>
 | 
			
		||||
 | 
			
		||||
        @include('portal.ninja2020.gateways.includes.payment_details')
 | 
			
		||||
 | 
			
		||||
        <form action="{{ route('client.payments.response') }}" method="post" id="server-response">
 | 
			
		||||
            @csrf
 | 
			
		||||
            <input type="hidden" name="company_gateway_id" value="{{ $gateway->getCompanyGatewayId() }}">
 | 
			
		||||
            <input type="hidden" name="payment_method_id" value="{{ $payment_method_id }}">
 | 
			
		||||
            <input type="hidden" name="source" value="">
 | 
			
		||||
            <input type="hidden" name="amount" value="{{ $amount }}">
 | 
			
		||||
            <input type="hidden" name="currency" value="{{ $currency }}">
 | 
			
		||||
            <input type="hidden" name="payment_hash" value="{{ $payment_hash }}">
 | 
			
		||||
        </form>
 | 
			
		||||
 | 
			
		||||
        @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')])
 | 
			
		||||
            @if (count($tokens) > 0)
 | 
			
		||||
                @foreach ($tokens as $token)
 | 
			
		||||
                    <label class="mr-4">
 | 
			
		||||
                        <input type="radio" data-token="{{ $token->token }}" name="payment-type"
 | 
			
		||||
                            class="form-radio cursor-pointer toggle-payment-with-token" />
 | 
			
		||||
                        <span class="ml-1 cursor-pointer">{{ App\Models\GatewayType::getAlias($token->gateway_type_id) }}
 | 
			
		||||
                            (#{{ $token->token }})</span>
 | 
			
		||||
                    </label>
 | 
			
		||||
                @endforeach
 | 
			
		||||
            @endisset
 | 
			
		||||
        @endcomponent
 | 
			
		||||
 | 
			
		||||
    @else
 | 
			
		||||
        @component('portal.ninja2020.components.general.card-element-single', ['title' => 'Direct Debit', 'show_title' => false])
 | 
			
		||||
            <span>{{ ctrans('texts.bank_account_not_linked') }}</span>
 | 
			
		||||
 | 
			
		||||
            <a class="button button-link text-primary"
 | 
			
		||||
                href="{{ route('client.payment_methods.index') }}">{{ ctrans('texts.add_payment_method') }}</a>
 | 
			
		||||
        @endcomponent
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    @if (count($tokens) > 0)
 | 
			
		||||
        @include('portal.ninja2020.gateways.includes.pay_now')
 | 
			
		||||
    @endif
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@script
 | 
			
		||||
    <script>
 | 
			
		||||
        Array
 | 
			
		||||
            .from(document.getElementsByClassName('toggle-payment-with-token'))
 | 
			
		||||
            .forEach((element) => element.addEventListener('click', (element) => {
 | 
			
		||||
                document.querySelector('input[name=source]').value = element.target.dataset.token;
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
        document.getElementById('pay-now').addEventListener('click', function() {
 | 
			
		||||
            document.getElementById('server-response').submit();
 | 
			
		||||
        });
 | 
			
		||||
    </script>
 | 
			
		||||
@endscript
 | 
			
		||||
@ -0,0 +1,56 @@
 | 
			
		||||
<div class="rounded-lg border bg-card text-card-foreground shadow-sm overflow-hidden py-5 bg-white sm:gap-4" id="gocardless-sepa-payment">
 | 
			
		||||
@if (count($tokens) > 0)
 | 
			
		||||
        <div class="alert alert-failure mb-4" hidden id="errors"></div>
 | 
			
		||||
 | 
			
		||||
        @include('portal.ninja2020.gateways.includes.payment_details')
 | 
			
		||||
 | 
			
		||||
        <form action="{{ route('client.payments.response') }}" method="post" id="server-response">
 | 
			
		||||
            @csrf
 | 
			
		||||
            <input type="hidden" name="company_gateway_id" value="{{ $gateway->getCompanyGatewayId() }}">
 | 
			
		||||
            <input type="hidden" name="payment_method_id" value="{{ $payment_method_id }}">
 | 
			
		||||
            <input type="hidden" name="source" value="">
 | 
			
		||||
            <input type="hidden" name="amount" value="{{ $amount }}">
 | 
			
		||||
            <input type="hidden" name="currency" value="{{ $currency }}">
 | 
			
		||||
            <input type="hidden" name="payment_hash" value="{{ $payment_hash }}">
 | 
			
		||||
        </form>
 | 
			
		||||
 | 
			
		||||
        @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')])
 | 
			
		||||
            @if (count($tokens) > 0)
 | 
			
		||||
                @foreach ($tokens as $token)
 | 
			
		||||
                    <label class="mr-4">
 | 
			
		||||
                        <input type="radio" data-token="{{ $token->token }}" name="payment-type"
 | 
			
		||||
                            class="form-radio cursor-pointer toggle-payment-with-token" />
 | 
			
		||||
                        <span class="ml-1 cursor-pointer">{{ ctrans('texts.payment_type_SEPA') }}
 | 
			
		||||
                            (#{{ $token->token }})</span>
 | 
			
		||||
                    </label>
 | 
			
		||||
                @endforeach
 | 
			
		||||
            @endisset
 | 
			
		||||
        @endcomponent
 | 
			
		||||
 | 
			
		||||
    @else
 | 
			
		||||
        @component('portal.ninja2020.components.general.card-element-single', ['title' => ctrans('texts.payment_type_SEPA'), 'show_title' => false])
 | 
			
		||||
            <span>{{ ctrans('texts.bank_account_not_linked') }}</span>
 | 
			
		||||
            
 | 
			
		||||
            <a class="button button-link text-primary"
 | 
			
		||||
                href="{{ route('client.payment_methods.index') }}">{{ ctrans('texts.add_payment_method') }}</a>
 | 
			
		||||
        @endcomponent
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    @if (count($tokens) > 0)
 | 
			
		||||
        @include('portal.ninja2020.gateways.includes.pay_now')
 | 
			
		||||
    @endif
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@script
 | 
			
		||||
    <script>
 | 
			
		||||
        Array
 | 
			
		||||
            .from(document.getElementsByClassName('toggle-payment-with-token'))
 | 
			
		||||
            .forEach((element) => element.addEventListener('click', (element) => {
 | 
			
		||||
                document.querySelector('input[name=source]').value = element.target.dataset.token;
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
        document.getElementById('pay-now').addEventListener('click', function() {
 | 
			
		||||
            document.getElementById('server-response').submit();
 | 
			
		||||
        });
 | 
			
		||||
    </script>
 | 
			
		||||
@endscript
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user