Forte gateway added.

This commit is contained in:
Kishan Patel 2022-04-18 08:17:08 +05:30
parent 711312df31
commit f4b590228a
10 changed files with 999 additions and 0 deletions

View File

@ -63,6 +63,8 @@ class Gateway extends StaticModel
$link = 'https://applications.sagepay.com/apply/2C02C252-0F8A-1B84-E10D-CF933EFCAA99';
} elseif ($this->id == 20 || $this->id == 56) {
$link = 'https://dashboard.stripe.com/account/apikeys';
} elseif ($this->id == 59) {
$link = 'https://www.forte.net/';
}
return $link;
@ -170,6 +172,12 @@ class Gateway extends StaticModel
GatewayType::HOSTED_PAGE => ['refund' => false, 'token_billing' => false, 'webhooks' => [' ']] // Razorpay
];
break;
case 59:
return [
GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true], // Forte
GatewayType::BANK_TRANSFER => ['refund' => true, 'token_billing' => true, 'webhooks' => [' ']],
];
break;
default:
return [];
break;

View File

@ -0,0 +1,231 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\PaymentDrivers\Forte;
use App\Models\GatewayType;
use App\Http\Requests\Request;
use App\Utils\Traits\MakesHash;
use Illuminate\Support\Facades\Validator;
use App\PaymentDrivers\FortePaymentDriver;
use App\Models\Payment;
class ACH
{
use MakesHash;
public $forte;
private $forte_base_uri="";
private $forte_api_access_id="";
private $forte_secure_key="";
private $forte_auth_organization_id="";
private $forte_organization_id="";
private $forte_location_id="";
public function __construct(FortePaymentDriver $forte)
{
$this->forte = $forte;
}
public function authorizeView(array $data)
{
return render('gateways.forte.ach.authorize', $data);
}
public function authorizeResponse(Request $request)
{
$customer_token = null;
$request->validate([
'account_number'=>'required|numeric',
'account_holder_name'=>'required|string',
'routing_number'=>'required|numeric',
]);
if ($this->forte->client->gateway_tokens->count() == 0) {
try {
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $this->forte_base_uri.'organizations/'.$this->forte_organization_id.'/locations/'.$this->forte_location_id.'/customers/',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"first_name": "'.$this->forte->client->name.'",
"last_name": "'.$this->forte->client->name.'",
"company_name": "'.$this->forte->client->name.'",
"customer_id": "'.$this->forte->client->number.'"
}',
CURLOPT_HTTPHEADER => array(
'X-Forte-Auth-Organization-Id: '.$this->forte_organization_id,
'Content-Type: application/json',
'Authorization: Basic '.base64_encode($this->forte_api_access_id.':'.$this->forte_secure_key),
'Cookie: visid_incap_621087=QJCccwHeTHinK5DnAeQIuXPk5mAAAAAAQUIPAAAAAAATABmm7IZkHhUi85sN+UaS; nlbi_621087=eeFJXPvhGXW3XVl0R1efXgAAAAC5hY2Arn4aSDDQA+R2vZZu; incap_ses_713_621087=IuVrdOb1HwK0pTS8ExblCT8B6GAAAAAAWyswWx7wzWve4j23+Nsp4w=='
),
));
$response = curl_exec($curl);
$httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
$response=json_decode($response);
if ($httpcode>299) {
$error = Validator::make([], []);
$error->getMessageBag()->add('gateway_error', $response->response->response_desc);
return redirect()->back()->withErrors($error);
}
$customer_token=$response->customer_token;
} catch (\Throwable $th) {
throw $th;
}
}else{
$customer_token = $this->forte->client->gateway_tokens[0]->gateway_customer_reference;
}
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $this->forte_base_uri.'organizations/'.$this->forte_organization_id.'/locations/'.$this->forte_location_id.'/customers/'.$customer_token.'/paymethods',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"notes":"'.$request->account_holder_name.' echeck",
"echeck": {
"account_holder": "'.$request->account_holder_name.'",
"account_number":"'.$request->account_number.'",
"routing_number":"'.$request->routing_number.'",
"account_type":"checking"
}
}',
CURLOPT_HTTPHEADER => array(
'X-Forte-Auth-Organization-Id: '.$this->forte_organization_id,
'Content-Type: application/json',
'Authorization: Basic '.base64_encode($this->forte_api_access_id.':'.$this->forte_secure_key),
'Cookie: visid_incap_621087=QJCccwHeTHinK5DnAeQIuXPk5mAAAAAAQUIPAAAAAAATABmm7IZkHhUi85sN+UaS; nlbi_621087=tVVcSY5O+xzIMhyvR1efXgAAAABn4GsrsejFXewG9LEvz7cm; incap_ses_9153_621087=wAileyRCBU3lBWqsNP0Ff80/6GAAAAAASCPsRmBm9ygyrCA0iBX3kg==; incap_ses_9210_621087=OHvJaqfG9Cc+r/0GZX7Qf10a6WAAAAAA1CWMfnTjC/4Y/4bz/HTgBg==; incap_ses_713_621087=Lu/yR4IM2iokOlO8ExblCSWB6WAAAAAANBLUy0jRk/4YatHkXIajvA=='
),
));
$response = curl_exec($curl);
$httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
$response=json_decode($response);
if ($httpcode>299) {
$error = Validator::make([], []);
$error->getMessageBag()->add('gateway_error', $response->response->response_desc);
return redirect()->back()->withErrors($error);
}
$payment_meta = new \stdClass;
// $payment_meta->brand = (string)sprintf('%s (%s)', $request->bank_name, ctrans('texts.ach'));
$payment_meta->brand = (string)ctrans('texts.ach');
$payment_meta->last4 = (string)$response->echeck->last_4_account_number;
$payment_meta->exp_year = '-';
$payment_meta->type = GatewayType::BANK_TRANSFER;
$data = [
'payment_meta' => $payment_meta,
'token' => $response->paymethod_token,
'payment_method_id' => $request->gateway_type_id,
];
$this->forte->storeGatewayToken($data, ['gateway_customer_reference' => $customer_token]);
return redirect()->route('client.payment_methods.index');
}
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;
$data['system_amount_with_fee'] = $data['amount_with_fee'];
$data['fee_percent'] = $this->forte->company_gateway->fees_and_limits->{GatewayType::BANK_TRANSFER}->fee_percent;
$data['total']['fee_total'] = $data['total']['invoice_totals'] * $data['fee_percent'] / 100;
$data['total']['amount_with_fee'] = $data['total']['fee_total'] + $data['total']['invoice_totals'];
$data['amount_with_fee'] = $data['total']['amount_with_fee'];
return render('gateways.forte.ach.pay', $data);
}
public function paymentResponse($request)
{
$data=$request;
try {
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $this->forte_base_uri.'organizations/'.$this->forte_organization_id.'/locations/'.$this->forte_location_id.'/transactions',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"action":"sale",
"authorization_amount": '.$data->amount_with_fee.',
"paymethod_token": "'.$data->payment_token.'",
"echeck":{
"sec_code":"PPD",
},
"billing_address":{
"first_name": "'.auth()->user()->client->name.'",
"last_name": "'.auth()->user()->client->name.'"
}
}',
CURLOPT_HTTPHEADER => array(
'X-Forte-Auth-Organization-Id: '.$this->forte_organization_id,
'Content-Type: application/json',
'Authorization: Basic '.base64_encode($this->forte_api_access_id.':'.$this->forte_secure_key),
'Cookie: visid_incap_621087=u18+3REYR/iISgzZxOF5s2ODW2IAAAAAQUIPAAAAAADuGqKgECQLS81FcSDrmhGe; nlbi_621087=YHngadhJ2VU+yr7/R1efXgAAAAD3mQyhqmnLls8PRu4iN58G; incap_ses_1136_621087=CVdrXUdhIlm9WJNDieLDD4QVXGIAAAAAvBwvkUcwhM0+OwvdPm2stg=='
),
));
$response = curl_exec($curl);
$httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
$response=json_decode($response);
} catch (\Throwable $th) {
throw $th;
}
if ($httpcode>299) {
$error = Validator::make([], []);
$error->getMessageBag()->add('gateway_error', $response->response->response_desc);
return redirect('client/invoices')->withErrors($error);
}
$data['gateway_type_id']=GatewayType::CREDIT_CARD;
$data['amount']=$request->system_amount_with_fee;
$data['payment_type']=GatewayType::CREDIT_CARD;
$data['transaction_reference']=$response->transaction_id;
$payment=$this->forte->createPayment($data, Payment::STATUS_COMPLETED);
return redirect('client/invoices')->withSuccess('Invoice paid.');
}
}

View File

@ -0,0 +1,233 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\PaymentDrivers\Forte;
use App\Models\Payment;
use App\Models\GatewayType;
use App\Utils\Traits\MakesHash;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator;
use App\PaymentDrivers\FortePaymentDriver;
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
class CreditCard
{
use MakesHash;
public $forte;
private $forte_base_uri="";
private $forte_api_access_id="";
private $forte_secure_key="";
private $forte_auth_organization_id="";
private $forte_organization_id="";
private $forte_location_id="";
public function __construct(FortePaymentDriver $forte)
{
$this->forte = $forte;
}
public function authorizeView(array $data)
{
return render('gateways.forte.credit_card.authorize', $data);
}
public function authorizeResponse($request)
{
$customer_token = null;
$request->validate([
'card_number'=>'required',
'card_holders_name'=>'required|string',
'expiry_month'=>'required',
'expiry_year'=>'required',
'cvc'=>'required',
]);
if ($this->forte->client->gateway_tokens->count() == 0) {
try {
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $this->forte_base_uri.'organizations/'.$this->forte_organization_id.'/locations/'.$this->forte_location_id.'/customers/',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"first_name": "'.$this->forte->client->name.'",
"last_name": "'.$this->forte->client->name.'",
"company_name": "'.$this->forte->client->name.'",
"customer_id": "'.$this->forte->client->number.'"
}',
CURLOPT_HTTPHEADER => array(
'X-Forte-Auth-Organization-Id: '.$this->forte_organization_id,
'Content-Type: application/json',
'Authorization: Basic '.base64_encode($this->forte_api_access_id.':'.$this->forte_secure_key),
'Cookie: visid_incap_621087=QJCccwHeTHinK5DnAeQIuXPk5mAAAAAAQUIPAAAAAAATABmm7IZkHhUi85sN+UaS; nlbi_621087=eeFJXPvhGXW3XVl0R1efXgAAAAC5hY2Arn4aSDDQA+R2vZZu; incap_ses_713_621087=IuVrdOb1HwK0pTS8ExblCT8B6GAAAAAAWyswWx7wzWve4j23+Nsp4w=='
),
));
$response = curl_exec($curl);
$httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
$response=json_decode($response);
if ($httpcode>299) {
$error = Validator::make([], []);
$error->getMessageBag()->add('gateway_error', $response->response->response_desc);
return redirect()->back()->withErrors($error);
}
$customer_token=$response->customer_token;
} catch (\Throwable $th) {
throw $th;
}
}else{
$customer_token = $this->forte->client->gateway_tokens[0]->gateway_customer_reference;
}
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $this->forte_base_uri.'organizations/'.$this->forte_organization_id.'/locations/'.$this->forte_location_id.'/customers/'.$customer_token.'/paymethods',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"notes":"'.$request->card_holders_name.' Card",
"card": {
"name_on_card":"'.$request->card_holders_name.'",
"card_type":"'.$request->card_type.'",
"account_number":"'.str_replace(' ', '', $request->card_number).'",
"expire_month":'.$request->expiry_month.',
"expire_year":20'.$request->expiry_year.',
"card_verification_value": "'.$request->cvc.'"
}
}',
CURLOPT_HTTPHEADER => array(
'X-Forte-Auth-Organization-Id: '.$this->forte_organization_id,
'Content-Type: application/json',
'Authorization: Basic '.base64_encode($this->forte_api_access_id.':'.$this->forte_secure_key),
'Cookie: visid_incap_621087=QJCccwHeTHinK5DnAeQIuXPk5mAAAAAAQUIPAAAAAAATABmm7IZkHhUi85sN+UaS'
),
));
$response = curl_exec($curl);
$httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
$response=json_decode($response);
if ($httpcode>299) {
$error = Validator::make([], []);
$error->getMessageBag()->add('gateway_error', $response->response->response_desc);
return redirect()->back()->withErrors($error);
}
$payment_meta = new \stdClass;
$payment_meta->exp_month = (string) $response->card->expire_month;
$payment_meta->exp_year = (string) $response->card->expire_year;
$payment_meta->brand = (string) $response->card->card_type;
$payment_meta->last4 = (string) $response->card->last_4_account_number;
$payment_meta->type = GatewayType::CREDIT_CARD;
$data = [
'payment_meta' => $payment_meta,
'token' => $response->paymethod_token,
'payment_method_id' => $request->payment_method_id,
];
$this->forte->storeGatewayToken($data, ['gateway_customer_reference' => $customer_token]);
return redirect()->route('client.payment_methods.index');
}
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;
$data['system_amount_with_fee'] = $data['amount_with_fee'];
$data['fee_percent'] = $this->forte->company_gateway->fees_and_limits->{GatewayType::CREDIT_CARD}->fee_percent;
$data['total']['fee_total'] = $data['total']['invoice_totals'] * $data['fee_percent'] / 100;
$data['total']['amount_with_fee'] = $data['total']['fee_total'] + $data['total']['invoice_totals'];
$data['amount_with_fee'] = $data['total']['amount_with_fee'];
return render('gateways.forte.credit_card.pay', $data);
}
public function paymentResponse(PaymentResponseRequest $request)
{
$data=$request;
try {
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $this->forte_base_uri.'organizations/'.$this->forte_organization_id.'/locations/'.$this->forte_location_id.'/transactions',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"action":"sale",
"authorization_amount": '.$data->amount_with_fee.',
"service_fee_amount": '.$data->fee_total.',
"paymethod_token": "'.$data->payment_token.'",
"billing_address":{
"first_name": "'.auth()->user()->client->name.'",
"last_name": "'.auth()->user()->client->name.'"
}
}',
CURLOPT_HTTPHEADER => array(
'X-Forte-Auth-Organization-Id: '.$this->forte_organization_id,
'Content-Type: application/json',
'Authorization: Basic '.base64_encode($this->forte_api_access_id.':'.$this->forte_secure_key),
'Cookie: visid_incap_621087=u18+3REYR/iISgzZxOF5s2ODW2IAAAAAQUIPAAAAAADuGqKgECQLS81FcSDrmhGe; nlbi_621087=YHngadhJ2VU+yr7/R1efXgAAAAD3mQyhqmnLls8PRu4iN58G; incap_ses_1136_621087=CVdrXUdhIlm9WJNDieLDD4QVXGIAAAAAvBwvkUcwhM0+OwvdPm2stg=='
),
));
$response = curl_exec($curl);
$httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
$response=json_decode($response);
} catch (\Throwable $th) {
throw $th;
}
if ($httpcode>299) {
$error = Validator::make([], []);
$error->getMessageBag()->add('gateway_error', $response->response->response_desc);
return redirect('client/invoices')->withErrors($error);
}
$data['gateway_type_id']=GatewayType::CREDIT_CARD;
$data['amount']=$request->system_amount_with_fee;
$data['payment_type']=GatewayType::CREDIT_CARD;
$data['transaction_reference']=$response->transaction_id;
$payment=$this->forte->createPayment($data, Payment::STATUS_COMPLETED);
return redirect('client/invoices')->withSuccess('Invoice paid.');
}
}

View File

@ -0,0 +1,90 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\PaymentDrivers;
use App\Models\SystemLog;
use App\Models\GatewayType;
use App\Utils\Traits\MakesHash;
use App\PaymentDrivers\Forte\ACH;
use App\PaymentDrivers\Forte\CreditCard;
class FortePaymentDriver extends BaseDriver
{
use MakesHash;
public $refundable = true; //does this gateway support refunds?
public $token_billing = true; //does this gateway support token billing?
public $can_authorise_credit_card = true; //does this gateway support authorizations?
public $gateway; //initialized gateway
public $payment_method; //initialized payment method
public static $methods = [
GatewayType::CREDIT_CARD => CreditCard::class,
GatewayType::BANK_TRANSFER => ACH::class,
];
/**
* Returns the gateway types.
*/
public function gatewayTypes(): array
{
$types = [];
$types[] = GatewayType::CREDIT_CARD;
$types[] = GatewayType::BANK_TRANSFER;
return $types;
}
const SYSTEM_LOG_TYPE = SystemLog::TYPE_STRIPE; //define a constant for your gateway ie TYPE_YOUR_CUSTOM_GATEWAY - set the const in the SystemLog model
public function setPaymentMethod($payment_method_id)
{
$class = self::$methods[$payment_method_id];
$this->payment_method = new $class($this);
return $this;
}
public function authorizeView(array $data)
{
return $this->payment_method->authorizeView($data); //this is your custom implementation from here
}
public function authorizeResponse($request)
{
return $this->payment_method->authorizeResponse($request); //this is your custom implementation from here
}
public function processPaymentView(array $data)
{
return $this->payment_method->paymentView($data); //this is your custom implementation from here
}
public function processPaymentResponse($request)
{
return $this->payment_method->paymentResponse($request); //this is your custom implementation from here
}
// public function refund(Payment $payment, $amount, $return_client_response = false)
// {
// return $this->payment_method->yourRefundImplementationHere(); //this is your custom implementation from here
// }
// public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash)
// {
// return $this->payment_method->yourTokenBillingImplmentation(); //this is your custom implementation from here
// }
}

View File

@ -0,0 +1,49 @@
<?php
use App\Models\Gateway;
use App\Models\GatewayType;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class FortePaymentGateway extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$fields = new \stdClass;
$fields->baseUri = "";
$fields->apiAccessId = "";
$fields->secureKey = "";
$fields->authOrganizationId = "";
$fields->organizationId = "";
$fields->locationId = "";
$forte = new Gateway;
$forte->id = 59;
$forte->name = 'Forte';
$forte->key = 'kivcvjexxvdiyqtj3mju5d6yhpeht2xs';
$forte->provider = 'Forte';
$forte->is_offsite = true;
$forte->fields = \json_encode($fields);
$forte->visible = 1;
$forte->site_url = 'https://www.forte.net/';
$forte->default_gateway_type_id = GatewayType::CREDIT_CARD;
$forte->save();
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@ -0,0 +1,108 @@
@extends('portal.ninja2020.layout.payments', ['gateway_title' => 'Bank Details', 'card_title' => 'Bank Details'])
@section('gateway_head')
{{-- @if($gateway->company_gateway->getConfigField('account_id'))
<meta name="stripe-account-id" content="{{ $gateway->company_gateway->getConfigField('account_id') }}">
<meta name="stripe-publishable-key" content="{{ config('ninja.ninja_stripe_publishable_key') }}">
@else --}}
{{-- <meta name="stripe-publishable-key" content="{{ $gateway->company_gateway->getPublishableKey() }}"> --}}
{{-- @endif --}}
@endsection
@section('gateway_content')
@if(session()->has('ach_error'))
<div class="alert alert-failure mb-4">
<p>{{ session('ach_error') }}</p>
</div>
@endif
@if(Session::has('error'))
<div class="alert alert-failure mb-4" id="errors">{{ Session::get('error') }}</div>
@endif
@if ($errors->any())
<div class="alert alert-failure mb-4">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('client.payment_methods.store', ['method' => App\Models\GatewayType::BANK_TRANSFER]) }}" method="post" id="server_response">
@csrf
{{-- <input type="hidden" name="company_gateway_id" value="{{ $gateway->company_gateway->id }}"> --}}
<input type="hidden" name="gateway_type_id" value="2">
<input type="hidden" name="gateway_response" id="gateway_response">
<input type="hidden" name="is_default" id="is_default">
<div class="alert alert-failure mb-4" hidden id="errors"></div>
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.account_holder_type')])
<span class="flex items-center mr-4">
<input class="form-radio mr-2" type="radio" value="individual" name="account-holder-type" checked>
<span>{{ __('texts.individual_account') }}</span>
</span>
<span class="flex items-center">
<input class="form-radio mr-2" type="radio" value="company" name="account-holder-type">
<span>{{ __('texts.company_account') }}</span>
</span>
@endcomponent
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.account_holder_name')])
<input class="input w-full" id="account-holder-name" type="text" name="account_holder_name" placeholder="{{ ctrans('texts.name') }}" required>
@endcomponent
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.country')])
<select name="countries" id="country" name="country" class="form-select input w-full" required>
@foreach($countries as $country)
<option value="{{ $country->iso_3166_2 }}" {{$country->iso_3166_2 == 'US' ? "selected" : ""}}>{{ $country->iso_3166_2 }} ({{ $country->name }})</option>
@endforeach
</select>
@endcomponent
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.currency')])
<select name="currencies" id="currency" name="currency" class="form-select input w-full">
@foreach($currencies as $currency)
<option value="{{ $currency->code }}" {{$currency->code == 'USD' ? "selected" : ""}}>{{ $currency->code }} ({{ $currency->name }})</option>
@endforeach
</select>
@endcomponent
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.routing_number')])
<input class="input w-full" id="routing-number" name="routing_number" type="text" required>
@endcomponent
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.account_number')])
<input class="input w-full" id="account-number" name="account_number" type="text" required>
@endcomponent
@component('portal.ninja2020.components.general.card-element-single')
<input type="checkbox" class="form-checkbox mr-1" name="accept_terms" id="accept-terms" required>
<label for="accept-terms" class="cursor-pointer">{{ ctrans('texts.ach_authorization', ['company' => auth()->user()->company->present()->name, 'email' => auth('contact')->user()->client->company->settings->email]) }}</label>
@endcomponent
<div class="bg-white px-4 py-5 flex justify-end">
<button type="button"
onclick="submitACH()"
class="button button-primary bg-primary {{ $class ?? '' }}">
<svg class="animate-spin h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<span>{{ $slot ?? ctrans('texts.add_payment_method') }}</span>
</button>
<input type="submit" style="display: none" id="form_btn">
</div>
</form>
@endsection
@section('gateway_footer')
<script>
function submitACH(){
let button = document.querySelector("#form_btn");
button.click();
}
</script>
@endsection

View File

@ -0,0 +1,80 @@
@extends('portal.ninja2020.layout.payments', ['gateway_title' => 'Bank Transfer', 'card_title' => 'Bank Transfer'])
@section('gateway_head')
{{-- <meta name="authorize-public-key" content="{{ $public_client_id }}">
<meta name="authorize-login-id" content="{{ $api_login_id }}"> --}}
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="{{ asset('js/clients/payments/card-js.min.js') }}"></script>
<link href="{{ asset('css/card-js.min.css') }}" rel="stylesheet" type="text/css">
@endsection
@section('gateway_content')
<form action="{{ route('client.payments.response') }}" method="post" id="server_response">
@csrf
<input type="hidden" name="payment_hash" value="{{ $payment_hash }}">
<input type="hidden" name="company_gateway_id" value="{{ $gateway->forte->company_gateway->id }}">
<input type="hidden" name="payment_method_id" value="{{$payment_method_id}}">
<input type="hidden" name="gateway_response" id="gateway_response">
<input type="hidden" name="dataValue" id="dataValue"/>
<input type="hidden" name="dataDescriptor" id="dataDescriptor"/>
<input type="hidden" name="token" id="token"/>
<input type="hidden" name="store_card" id="store_card"/>
<input type="hidden" name="amount_with_fee" id="amount_with_fee" value="{{ $total['amount_with_fee'] }}"/>
<input type="hidden" name="system_amount_with_fee" id="system_amount_with_fee" value="{{ $system_amount_with_fee }}"/>
<input type="hidden" name="fee_total" id="fee_total" value="{{ $total['fee_total'] }}"/>
<div id="errors"></div>
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_type')])
Bank Transfer
@endcomponent
@include('portal.ninja2020.gateways.includes.payment_details')
@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->hashed_id }}"
name="payment_token"
id="payment_token"
value="{{ $token->token }}"
class="form-radio cursor-pointer toggle-payment-with-token"/>
<span class="ml-1 cursor-pointer">**** {{ optional($token->meta)->last4 }}</span>
</label>
@endforeach
@endisset
@endcomponent
<div class="bg-white px-4 py-5 flex justify-end">
<button type="button"
onclick="submitPay()"
class="button button-primary bg-primary {{ $class ?? '' }}">
<svg class="animate-spin h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<span>{{ $slot ?? ctrans('texts.pay_now') }}</span>
<input type="submit" style="display: none" id="form_btn">
</button>
</div>
</form>
@endsection
@section('gateway_footer')
<script>
function submitPay(){
if ($("input:radio[name='payment_token']").is(":checked") == true) {
let button = document.querySelector("#form_btn");
button.click();
}else{
document.getElementById('errors').innerHTML='<div class="alert alert-failure mb-4">Please select payemnt method</div>'
}
}
</script>
@endsection

View File

@ -0,0 +1,108 @@
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.credit_card'), 'card_title' => ctrans('texts.credit_card')])
@section('gateway_head')
{{-- <meta name="authorize-public-key" content="{{ $public_client_id }}">
<meta name="authorize-login-id" content="{{ $api_login_id }}"> --}}
<meta name="year-invalid" content="{{ ctrans('texts.year_invalid') }}">
<meta name="month-invalid" content="{{ ctrans('texts.month_invalid') }}">
<meta name="credit-card-invalid" content="{{ ctrans('texts.credit_card_invalid') }}">
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="{{ asset('js/clients/payments/card-js.min.js') }}"></script>
<link href="{{ asset('css/card-js.min.css') }}" rel="stylesheet" type="text/css">
@endsection
@section('gateway_content')
<form action="{{ route('client.payment_methods.store', ['method' => App\Models\GatewayType::CREDIT_CARD]) }}"
method="post" id="server_response">
@csrf
{{-- <input type="hidden" name="company_gateway_id" value="{{ $gateway->company_gateway->id }}"> --}}
<input type="hidden" name="payment_method_id" value="1">
<input type="hidden" name="gateway_response" id="gateway_response">
<input type="hidden" name="is_default" id="is_default">
<input type="hidden" name="dataValue" id="dataValue"/>
<input type="hidden" name="dataDescriptor" id="dataDescriptor"/>
<input type="hidden" name="expiry_month" id="expiration_month">
<input type="hidden" name="expiry_year" id="expiration_year">
<input type="hidden" name="card_type" id="card_type">
@if(!Request::isSecure())
<p class="alert alert-failure">{{ ctrans('texts.https_required') }}</p>
@endif
@if(Session::has('error'))
<div class="alert alert-failure mb-4" id="errors">{{ Session::get('error') }}</div>
@endif
@if ($errors->any())
<div class="alert alert-failure mb-4">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.method')])
{{ ctrans('texts.credit_card') }}
@endcomponent
@include('portal.ninja2020.gateways.forte.includes.credit_card')
<div class="bg-white px-4 py-5 flex justify-end">
<button type="button"
onclick="submitCard()"
class="button button-primary bg-primary {{ $class ?? '' }}">
<svg class="animate-spin h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<span>{{ $slot ?? ctrans('texts.add_payment_method') }}</span>
</button>
<input type="submit" style="display: none" id="form_btn">
</div>
</form>
{{-- @component('portal.ninja2020.gateways.includes.pay_now', ['id' => 'card_button'])
{{ ctrans('texts.add_payment_method') }}
@endcomponent --}}
@endsection
@section('gateway_footer')
{{-- @if($gateway->company_gateway->getConfigField('testMode'))
<script src="https://jstest.authorize.net/v1/Accept.js" charset="utf-8"></script>
@else
<script src="https://js.authorize.net/v1/Accept.js" charset="utf-8"></script>
@endif
<script src="{{ asset('js/clients/payment_methods/authorize-authorize-card.js') }}"></script> --}}
<script>
function submitCard(){
var doc = document.getElementsByClassName("card-number-wrapper");
var cardType=doc[0].childNodes[1].classList[2];
if (cardType=='master-card') {
document.getElementById('card_type').value='mast';
} else if(cardType=='visa') {
document.getElementById('card_type').value='visa';
}else if(cardType=='jcb') {
document.getElementById('card_type').value='jcb';
}else if(cardType=='discover') {
document.getElementById('card_type').value='disc';
}else if(cardType=='american-express') {
document.getElementById('card_type').value='amex';
}else{
document.getElementById('card_type').value=cardType;
}
var month=document.querySelector('input[name=expiry-month]').value;
var year=document.querySelector('input[name=expiry-year]').value;
document.getElementById('expiration_month').value=month;
document.getElementById('expiration_year').value=year;
let button = document.querySelector("#form_btn");
button.click();
}
</script>
@endsection

View File

@ -0,0 +1,80 @@
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' => ctrans('texts.payment_type_credit_card')])
@section('gateway_head')
{{-- <meta name="authorize-public-key" content="{{ $public_client_id }}">
<meta name="authorize-login-id" content="{{ $api_login_id }}"> --}}
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="{{ asset('js/clients/payments/card-js.min.js') }}"></script>
<link href="{{ asset('css/card-js.min.css') }}" rel="stylesheet" type="text/css">
@endsection
@section('gateway_content')
<form action="{{ route('client.payments.response') }}" method="post" id="server_response">
@csrf
<input type="hidden" name="payment_hash" value="{{ $payment_hash }}">
<input type="hidden" name="company_gateway_id" value="{{ $gateway->forte->company_gateway->id }}">
<input type="hidden" name="payment_method_id" value="{{$payment_method_id}}">
<input type="hidden" name="gateway_response" id="gateway_response">
<input type="hidden" name="dataValue" id="dataValue"/>
<input type="hidden" name="dataDescriptor" id="dataDescriptor"/>
<input type="hidden" name="token" id="token"/>
<input type="hidden" name="store_card" id="store_card"/>
<input type="hidden" name="amount_with_fee" id="amount_with_fee" value="{{ $total['amount_with_fee'] }}"/>
<input type="hidden" name="system_amount_with_fee" id="system_amount_with_fee" value="{{ $system_amount_with_fee }}"/>
<input type="hidden" name="fee_total" id="fee_total" value="{{ $total['fee_total'] }}"/>
<div id="errors"></div>
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_type')])
{{ ctrans('texts.credit_card') }}
@endcomponent
@include('portal.ninja2020.gateways.includes.payment_details')
@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->hashed_id }}"
name="payment_token"
id="payment_token"
value="{{ $token->token }}"
class="form-radio cursor-pointer toggle-payment-with-token"/>
<span class="ml-1 cursor-pointer">**** {{ optional($token->meta)->last4 }}</span>
</label>
@endforeach
@endisset
@endcomponent
<div class="bg-white px-4 py-5 flex justify-end">
<button type="button"
onclick="submitPay()"
class="button button-primary bg-primary {{ $class ?? '' }}">
<svg class="animate-spin h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<span>{{ $slot ?? ctrans('texts.pay_now') }}</span>
<input type="submit" style="display: none" id="form_btn">
</button>
</div>
</form>
@endsection
@section('gateway_footer')
<script>
function submitPay(){
if ($("input:radio[name='payment_token']").is(":checked") == true) {
let button = document.querySelector("#form_btn");
button.click();
}else{
document.getElementById('errors').innerHTML='<div class="alert alert-failure mb-4">Please select payemnt method</div>'
}
}
</script>
@endsection

View File

@ -0,0 +1,12 @@
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
style="display: flex!important; justify-content: center!important;" id="authorize--credit-card-container">
<div class="card-js" id="my-card" data-capture-name="true">
<input class="name" id="cardholder_name" name="card_holders_name" placeholder="{{ ctrans('texts.name')}}">
<input class="card-number my-custom-class" id="card_number" name="card_number">
<input type="hidden" name="expiry_month" id="expiration_month">
<input type="hidden" name="expiry_year" id="expiration_year">
<input class="cvc" name="cvc" id="cvv">
</div>
<div id="errors"></div>
</div>