mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Add Plaid support
This commit is contained in:
parent
92552dc94f
commit
d78b874838
@ -391,7 +391,7 @@ class PaymentController extends BaseController
|
|||||||
'last_name' => 'required',
|
'last_name' => 'required',
|
||||||
];
|
];
|
||||||
|
|
||||||
if ( ! Input::get('stripeToken') && ! Input::get('payment_method_nonce')) {
|
if ( ! Input::get('stripeToken') && ! Input::get('payment_method_nonce') && !(Input::get('plaidPublicToken') && Input::get('plaidAccountId'))) {
|
||||||
$rules = array_merge(
|
$rules = array_merge(
|
||||||
$rules,
|
$rules,
|
||||||
[
|
[
|
||||||
@ -447,11 +447,6 @@ class PaymentController extends BaseController
|
|||||||
|
|
||||||
// check if we're creating/using a billing token
|
// check if we're creating/using a billing token
|
||||||
if ($accountGateway->gateway_id == GATEWAY_STRIPE) {
|
if ($accountGateway->gateway_id == GATEWAY_STRIPE) {
|
||||||
if ($token = Input::get('stripeToken')) {
|
|
||||||
$details['token'] = $token;
|
|
||||||
unset($details['card']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($useToken) {
|
if ($useToken) {
|
||||||
$details['customerReference'] = $client->getGatewayToken();
|
$details['customerReference'] = $client->getGatewayToken();
|
||||||
unset($details['token']);
|
unset($details['token']);
|
||||||
@ -464,7 +459,7 @@ class PaymentController extends BaseController
|
|||||||
$details['token'] = $token;
|
$details['token'] = $token;
|
||||||
$details['customerReference'] = $customerReference;
|
$details['customerReference'] = $customerReference;
|
||||||
|
|
||||||
if ($paymentType == PAYMENT_TYPE_STRIPE_ACH && empty($usingPlaid) ) {
|
if ($paymentType == PAYMENT_TYPE_STRIPE_ACH && empty(Input::get('plaidPublicToken')) ) {
|
||||||
// The user needs to complete verification
|
// The user needs to complete verification
|
||||||
Session::flash('message', trans('texts.bank_account_verification_next_steps'));
|
Session::flash('message', trans('texts.bank_account_verification_next_steps'));
|
||||||
return Redirect::to('/client/paymentmethods');
|
return Redirect::to('/client/paymentmethods');
|
||||||
|
@ -794,10 +794,16 @@ class PublicClientController extends BaseController
|
|||||||
|
|
||||||
if ($sourceToken) {
|
if ($sourceToken) {
|
||||||
$details = array('token' => $sourceToken);
|
$details = array('token' => $sourceToken);
|
||||||
|
} elseif (Input::get('plaidPublicToken')) {
|
||||||
|
$usingPlaid = true;
|
||||||
|
$details = array('plaidPublicToken' => Input::get('plaidPublicToken'), 'plaidAccountId' => Input::get('plaidAccountId'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($details)) {
|
||||||
$gateway = $this->paymentService->createGateway($accountGateway);
|
$gateway = $this->paymentService->createGateway($accountGateway);
|
||||||
$sourceId = $this->paymentService->createToken($gateway, $details, $accountGateway, $client, $invitation->contact_id);
|
$sourceId = $this->paymentService->createToken($gateway, $details, $accountGateway, $client, $invitation->contact_id);
|
||||||
} else {
|
} else {
|
||||||
return Redirect::to('payment/'.$invitationKey)->withInput(Request::except('cvv'));
|
return Redirect::to('payment/'.$invitation->invitation_key)->withInput(Request::except('cvv'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(empty($sourceId)) {
|
if(empty($sourceId)) {
|
||||||
|
@ -117,7 +117,7 @@ class AccountGateway extends EntityModel
|
|||||||
|
|
||||||
$stripe_key = $this->getPublishableStripeKey();
|
$stripe_key = $this->getPublishableStripeKey();
|
||||||
|
|
||||||
return substr(trim($stripe_key), 0, 8) == 'sk_test_' ? 'tartan' : 'production';
|
return substr(trim($stripe_key), 0, 8) == 'pk_test_' ? 'tartan' : 'production';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +93,17 @@ class PaymentService extends BaseService
|
|||||||
$data['ButtonSource'] = 'InvoiceNinja_SP';
|
$data['ButtonSource'] = 'InvoiceNinja_SP';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if($input && $accountGateway->isGateway(GATEWAY_STRIPE)) {
|
||||||
|
if (!empty($input['stripeToken'])) {
|
||||||
|
$data['token'] = $input['stripeToken'];
|
||||||
|
unset($details['card']);
|
||||||
|
} elseif (!empty($input['plaidPublicToken'])) {
|
||||||
|
$data['plaidPublicToken'] = $input['plaidPublicToken'];
|
||||||
|
$data['plaidAccountId'] = $input['plaidAccountId'];
|
||||||
|
unset($data['card']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,22 +293,49 @@ class PaymentService extends BaseService
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($accountGateway->gateway->id == GATEWAY_STRIPE) {
|
if ($accountGateway->gateway->id == GATEWAY_STRIPE) {
|
||||||
$tokenResponse = $gateway->createCard($details)->send();
|
if (!empty($details['plaidPublicToken'])) {
|
||||||
$sourceReference = $tokenResponse->getCardReference();
|
$plaidResult = $this->getPlaidToken($accountGateway, $details['plaidPublicToken'], $details['plaidAccountId']);
|
||||||
$customerReference = $tokenResponse->getCustomerReference();
|
|
||||||
|
|
||||||
if (!$sourceReference) {
|
if (is_string($plaidResult)) {
|
||||||
$responseData = $tokenResponse->getData();
|
$this->lastError = $plaidResult;
|
||||||
if ($responseData['object'] == 'bank_account' || $responseData['object'] == 'card') {
|
return;
|
||||||
$sourceReference = $responseData['id'];
|
} elseif (!$plaidResult) {
|
||||||
|
$this->lastError = 'No token received from Plaid';
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unset($details['plaidPublicToken']);
|
||||||
|
unset($details['plaidAccountId']);
|
||||||
|
$details['token'] = $plaidResult['stripe_bank_account_token'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($customerReference == $sourceReference) {
|
$tokenResponse = $gateway->createCard($details)->send();
|
||||||
// This customer was just created; find the card
|
|
||||||
|
if ($tokenResponse->isSuccessful()) {
|
||||||
|
$sourceReference = $tokenResponse->getCardReference();
|
||||||
|
if (!$customerReference) {
|
||||||
|
$customerReference = $tokenResponse->getCustomerReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$sourceReference) {
|
||||||
|
$responseData = $tokenResponse->getData();
|
||||||
|
if (!empty($responseData['object']) && ($responseData['object'] == 'bank_account' || $responseData['object'] == 'card')) {
|
||||||
|
$sourceReference = $responseData['id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($customerReference == $sourceReference) {
|
||||||
|
// This customer was just created; find the card
|
||||||
|
$data = $tokenResponse->getData();
|
||||||
|
if (!empty($data['default_source'])) {
|
||||||
|
$sourceReference = $data['default_source'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
$data = $tokenResponse->getData();
|
$data = $tokenResponse->getData();
|
||||||
if (!empty($data['default_source'])) {
|
if ($data && $data['error'] && $data['error']['type'] == 'invalid_request_error') {
|
||||||
$sourceReferebce = $data['default_source'];
|
$this->lastError = $data['error']['message'];
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($accountGateway->gateway->id == GATEWAY_BRAINTREE) {
|
} elseif ($accountGateway->gateway->id == GATEWAY_BRAINTREE) {
|
||||||
@ -312,7 +350,7 @@ class PaymentService extends BaseService
|
|||||||
$details['customerId'] = $customerReference;
|
$details['customerId'] = $customerReference;
|
||||||
|
|
||||||
$tokenResponse = $gateway->createPaymentMethod($details)->send();
|
$tokenResponse = $gateway->createPaymentMethod($details)->send();
|
||||||
$cardReference = $tokenResponse->getData()->paymentMethod->token;
|
$sourceReference = $tokenResponse->getData()->paymentMethod->token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -809,4 +847,45 @@ class PaymentService extends BaseService
|
|||||||
return $e->getMessage();
|
return $e->getMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getPlaidToken($accountGateway, $publicToken, $accountId) {
|
||||||
|
$clientId = $accountGateway->getPlaidClientId();
|
||||||
|
$secret = $accountGateway->getPlaidSecret();
|
||||||
|
|
||||||
|
if (!$clientId) {
|
||||||
|
return 'No client ID set';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$secret) {
|
||||||
|
return 'No secret set';
|
||||||
|
}
|
||||||
|
|
||||||
|
try{
|
||||||
|
$subdomain = $accountGateway->getPlaidEnvironment() == 'production' ? 'api' : 'tartan';
|
||||||
|
$response = (new \GuzzleHttp\Client(['base_uri'=>"https://{$subdomain}.plaid.com"]))->request(
|
||||||
|
'POST',
|
||||||
|
'exchange_token',
|
||||||
|
[
|
||||||
|
'allow_redirects' => false,
|
||||||
|
'headers' => ['content-type' => 'application/x-www-form-urlencoded'],
|
||||||
|
'body' => http_build_query(array(
|
||||||
|
'client_id' => $clientId,
|
||||||
|
'secret' => $secret,
|
||||||
|
'public_token' => $publicToken,
|
||||||
|
'account_id' => $accountId,
|
||||||
|
))
|
||||||
|
]
|
||||||
|
);
|
||||||
|
return json_decode($response->getBody(), true);
|
||||||
|
} catch (\GuzzleHttp\Exception\BadResponseException $e) {
|
||||||
|
$response = $e->getResponse();
|
||||||
|
$body = json_decode($response->getBody(), true);
|
||||||
|
|
||||||
|
if ($body && !empty($body['message'])) {
|
||||||
|
return $body['message'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
12
public/images/plaid-logo.svg
Normal file
12
public/images/plaid-logo.svg
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 30 30" enable-background="new 0 0 30 30" xml:space="preserve">
|
||||||
|
<path id="XMLID_14_" fill="#275A76" d="M15.1,3.2l-3.2-3.3L2.5,2.3L0,11.6l3.2,3.3l-3.3,3.2l2.4,9.3l9.3,2.6l3.3-3.2l3.2,3.3
|
||||||
|
l9.3-2.4l2.6-9.3l-3.2-3.3l3.3-3.2l-2.4-9.3L18.4,0L15.1,3.2z M13.2,5l-3.1,3.1l-3.9-4l4.9-1.3L13.2,5z M15,16.9l3.1,3.1l-3.1,3.1
|
||||||
|
L11.8,20L15,16.9z M10,18.1l-3.1-3.1l3.1-3.1l3.1,3.1L10,18.1z M16.9,15l3.1-3.1l3.1,3.1L20,18.2L16.9,15z M15,13.1L11.9,10l3.1-3.1
|
||||||
|
l3.1,3.1L15,13.1z M2.9,10.9L4.3,6l3.9,4l-3.1,3.1L2.9,10.9z M5,16.8l3.1,3.1l-4,3.9l-1.3-4.9L5,16.8z M10.9,27.1L6,25.7l4-3.9
|
||||||
|
l3.1,3.1L10.9,27.1z M16.8,25l3.1-3.1l3.9,4l-4.9,1.3L16.8,25z M27.1,19.1L25.7,24l-3.9-4l3.1-3.1L27.1,19.1z M25,13.2l-3.1-3.1
|
||||||
|
l4-3.9l1.3,4.9L25,13.2z M24,4.3l-4,3.9l-3.1-3.1l2.2-2.2L24,4.3z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
12
public/images/plaid-logowhite.svg
Normal file
12
public/images/plaid-logowhite.svg
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 30 30" enable-background="new 0 0 30 30" xml:space="preserve">
|
||||||
|
<path id="XMLID_14_" fill="#FFFFFF" d="M15.1,3.2l-3.2-3.3L2.5,2.3L0,11.6l3.2,3.3l-3.3,3.2l2.4,9.3l9.3,2.6l3.3-3.2l3.2,3.3
|
||||||
|
l9.3-2.4l2.6-9.3l-3.2-3.3l3.3-3.2l-2.4-9.3L18.4,0L15.1,3.2z M13.2,5l-3.1,3.1l-3.9-4l4.9-1.3L13.2,5z M15,16.9l3.1,3.1l-3.1,3.1
|
||||||
|
L11.8,20L15,16.9z M10,18.1l-3.1-3.1l3.1-3.1l3.1,3.1L10,18.1z M16.9,15l3.1-3.1l3.1,3.1L20,18.2L16.9,15z M15,13.1L11.9,10l3.1-3.1
|
||||||
|
l3.1,3.1L15,13.1z M2.9,10.9L4.3,6l3.9,4l-3.1,3.1L2.9,10.9z M5,16.8l3.1,3.1l-4,3.9l-1.3-4.9L5,16.8z M10.9,27.1L6,25.7l4-3.9
|
||||||
|
l3.1,3.1L10.9,27.1z M16.8,25l3.1-3.1l3.9,4l-4.9,1.3L16.8,25z M27.1,19.1L25.7,24l-3.9-4l3.1-3.1L27.1,19.1z M25,13.2l-3.1-3.1
|
||||||
|
l4-3.9l1.3,4.9L25,13.2z M24,4.3l-4,3.9l-3.1-3.1l2.2-2.2L24,4.3z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -1259,6 +1259,10 @@ $LANG = array(
|
|||||||
'payment_method_error' => 'There was an error adding your payment methd. Please try again later.',
|
'payment_method_error' => 'There was an error adding your payment methd. Please try again later.',
|
||||||
'notification_invoice_payment_failed_subject' => 'Payment failed for Invoice :invoice',
|
'notification_invoice_payment_failed_subject' => 'Payment failed for Invoice :invoice',
|
||||||
'notification_invoice_payment_failed' => 'A payment made by client :client towards Invoice :invoice failed. The payment has been marked as failed and :amount has been added to the client\'s balance.',
|
'notification_invoice_payment_failed' => 'A payment made by client :client towards Invoice :invoice failed. The payment has been marked as failed and :amount has been added to the client\'s balance.',
|
||||||
|
'link_with_plaid' => 'Link Account Instantly with Plaid',
|
||||||
|
'link_manually' => 'Link Manually',
|
||||||
|
'secured_by_plaid' => 'Secured by Plaid',
|
||||||
|
'plaid_linked_status' => 'Your bank account at :bank'
|
||||||
);
|
);
|
||||||
|
|
||||||
return $LANG;
|
return $LANG;
|
||||||
|
@ -64,6 +64,8 @@
|
|||||||
Stripe.setPublishableKey('{{ $accountGateway->getPublishableStripeKey() }}');
|
Stripe.setPublishableKey('{{ $accountGateway->getPublishableStripeKey() }}');
|
||||||
$(function() {
|
$(function() {
|
||||||
$('.payment-form').submit(function(event) {
|
$('.payment-form').submit(function(event) {
|
||||||
|
if($('[name=plaidAccountId]').length)return;
|
||||||
|
|
||||||
var $form = $(this);
|
var $form = $(this);
|
||||||
|
|
||||||
var data = {
|
var data = {
|
||||||
@ -140,6 +142,31 @@
|
|||||||
// Prevent the form from submitting with the default action
|
// Prevent the form from submitting with the default action
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@if($accountGateway->getPlaidEnabled())
|
||||||
|
var plaidHandler = Plaid.create({
|
||||||
|
selectAccount: true,
|
||||||
|
env: '{{ $accountGateway->getPlaidEnvironment() }}',
|
||||||
|
clientName: {!! json_encode($account->getDisplayName()) !!},
|
||||||
|
key: '{{ $accountGateway->getPlaidPublicKey() }}',
|
||||||
|
product: 'auth',
|
||||||
|
onSuccess: plaidSuccessHandler,
|
||||||
|
onExit : function(){$('#secured_by_plaid').hide()}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#plaid_link_button').click(function(){plaidHandler.open();$('#secured_by_plaid').fadeIn()});
|
||||||
|
$('#plaid_unlink').click(function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
$('#manual_container').fadeIn();
|
||||||
|
$('#plaid_linked').hide();
|
||||||
|
$('#plaid_link_button').show();
|
||||||
|
$('#pay_now_button').hide();
|
||||||
|
$('#add_account_button').show();
|
||||||
|
$('[name=plaidPublicToken]').remove();
|
||||||
|
$('[name=plaidAccountId]').remove();
|
||||||
|
$('[name=account_holder_type],#account_holder_name').attr('required','required');
|
||||||
|
})
|
||||||
|
@endif
|
||||||
});
|
});
|
||||||
|
|
||||||
function stripeResponseHandler(status, response) {
|
function stripeResponseHandler(status, response) {
|
||||||
@ -164,6 +191,26 @@
|
|||||||
$form.get(0).submit();
|
$form.get(0).submit();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function plaidSuccessHandler(public_token, metadata) {
|
||||||
|
$('#secured_by_plaid').hide()
|
||||||
|
var $form = $('.payment-form');
|
||||||
|
|
||||||
|
$form.append($('<input type="hidden" name="plaidPublicToken"/>').val(public_token));
|
||||||
|
$form.append($('<input type="hidden" name="plaidAccountId"/>').val(metadata.account_id));
|
||||||
|
$('#plaid_linked_status').text('{{ trans('texts.plaid_linked_status') }}'.replace(':bank', metadata.institution.name));
|
||||||
|
$('#manual_container').fadeOut();
|
||||||
|
$('#plaid_linked').show();
|
||||||
|
$('#plaid_link_button').hide();
|
||||||
|
$('[name=account_holder_type],#account_holder_name').removeAttr('required');
|
||||||
|
|
||||||
|
|
||||||
|
var payNowBtn = $('#pay_now_button');
|
||||||
|
if(payNowBtn.length) {
|
||||||
|
payNowBtn.show();
|
||||||
|
$('#add_account_button').hide();
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
@else
|
@else
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
@ -364,67 +411,93 @@
|
|||||||
|
|
||||||
|
|
||||||
@if($paymentType == PAYMENT_TYPE_STRIPE_ACH)
|
@if($paymentType == PAYMENT_TYPE_STRIPE_ACH)
|
||||||
<p>{{ trans('texts.ach_verification_delay_help') }}</p>
|
@if($accountGateway->getPlaidEnabled())
|
||||||
<div class="row">
|
<div id="plaid_container">
|
||||||
<div class="col-md-6">
|
<a class="btn btn-default btn-lg" id="plaid_link_button">
|
||||||
<div class="radio">
|
<img src="{{ URL::to('images/plaid-logo.svg') }}">
|
||||||
{!! Former::radios('account_holder_type')->radios(array(
|
<img src="{{ URL::to('images/plaid-logowhite.svg') }}" class="hoverimg">
|
||||||
trans('texts.individual_account') => array('value' => 'individual'),
|
{{ trans('texts.link_with_plaid') }}
|
||||||
trans('texts.company_account') => array('value' => 'company'),
|
</a>
|
||||||
))->inline()->label(''); !!}
|
<div id="plaid_linked">
|
||||||
|
<div id="plaid_linked_status"></div>
|
||||||
|
<a href="#" id="plaid_unlink">{{ trans('texts.unlink') }}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
@endif
|
||||||
{!! Former::text('account_holder_name')
|
<div id="manual_container">
|
||||||
->placeholder(trans('texts.account_holder_name'))
|
@if($accountGateway->getPlaidEnabled())
|
||||||
->label('') !!}
|
<div id="plaid_or"><span>{{ trans('texts.or') }}</span></div>
|
||||||
|
<h4>{{ trans('texts.link_manually') }}</h4>
|
||||||
|
@endif
|
||||||
|
<p>{{ trans('texts.ach_verification_delay_help') }}</p>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="radio">
|
||||||
|
{!! Former::radios('account_holder_type')->radios(array(
|
||||||
|
trans('texts.individual_account') => array('value' => 'individual'),
|
||||||
|
trans('texts.company_account') => array('value' => 'company'),
|
||||||
|
))->inline()->label(''); !!}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
{!! Former::text('account_holder_name')
|
||||||
|
->placeholder(trans('texts.account_holder_name'))
|
||||||
|
->label('') !!}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="row">
|
||||||
<div class="row">
|
<div class="col-md-6">
|
||||||
<div class="col-md-6">
|
{!! Former::select('country')
|
||||||
{!! Former::select('country')
|
->placeholder(trans('texts.country_id'))
|
||||||
->placeholder(trans('texts.country_id'))
|
->fromQuery($countries, 'name', 'iso_3166_2')
|
||||||
->fromQuery($countries, 'name', 'iso_3166_2')
|
->addGroupClass('country-select')
|
||||||
->addGroupClass('country-select')
|
->label('') !!}
|
||||||
->label('') !!}
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
{!! Former::select('currency')
|
||||||
|
->placeholder(trans('texts.currency_id'))
|
||||||
|
->fromQuery($currencies, 'name', 'code')
|
||||||
|
->addGroupClass('currency-select')
|
||||||
|
->label('') !!}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="row">
|
||||||
{!! Former::select('currency')
|
<div class="col-md-6">
|
||||||
->placeholder(trans('texts.currency_id'))
|
{!! Former::text('')
|
||||||
->fromQuery($currencies, 'name', 'code')
|
->id('routing_number')
|
||||||
->addGroupClass('currency-select')
|
->placeholder(trans('texts.routing_number'))
|
||||||
->label('') !!}
|
->label('') !!}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div id="bank_name"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="row">
|
||||||
<div class="row">
|
<div class="col-md-6">
|
||||||
<div class="col-md-6">
|
{!! Former::text('')
|
||||||
{!! Former::text('')
|
->id('account_number')
|
||||||
->id('routing_number')
|
->placeholder(trans('texts.account_number'))
|
||||||
->placeholder(trans('texts.routing_number'))
|
->label('') !!}
|
||||||
->label('') !!}
|
</div>
|
||||||
</div>
|
<div class="col-md-6">
|
||||||
<div class="col-md-6">
|
{!! Former::text('')
|
||||||
<div id="bank_name"></div>
|
->id('confirm_account_number')
|
||||||
</div>
|
->placeholder(trans('texts.confirm_account_number'))
|
||||||
</div>
|
->label('') !!}
|
||||||
<div class="row">
|
</div>
|
||||||
<div class="col-md-6">
|
|
||||||
{!! Former::text('')
|
|
||||||
->id('account_number')
|
|
||||||
->placeholder(trans('texts.account_number'))
|
|
||||||
->label('') !!}
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
{!! Former::text('')
|
|
||||||
->id('confirm_account_number')
|
|
||||||
->placeholder(trans('texts.confirm_account_number'))
|
|
||||||
->label('') !!}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<center>
|
<center>
|
||||||
{!! Button::success(strtoupper(trans('texts.add_account')))
|
{!! Button::success(strtoupper(trans('texts.add_account')))
|
||||||
->submit()
|
->submit()
|
||||||
|
->withAttributes(['id'=>'add_account_button'])
|
||||||
->large() !!}
|
->large() !!}
|
||||||
|
@if($accountGateway->getPlaidEnabled() && !empty($amount))
|
||||||
|
{!! Button::success(strtoupper(trans('texts.pay_now') . ' - ' . $account->formatMoney($amount, $client, true) ))
|
||||||
|
->submit()
|
||||||
|
->withAttributes(['style'=>'display:none', 'id'=>'pay_now_button'])
|
||||||
|
->large() !!}
|
||||||
|
@endif
|
||||||
</center>
|
</center>
|
||||||
@else
|
@else
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -607,5 +680,8 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@if ($accountGateway->getPlaidEnabled())
|
||||||
|
<a href="https://plaid.com/products/auth/" target="_blank" style="display:none" id="secured_by_plaid"><img src="{{ URL::to('images/plaid-logowhite.svg') }}">{{ trans('texts.secured_by_plaid') }}</a>
|
||||||
|
<script src="https://cdn.plaid.com/link/stable/link-initialize.js"></script>
|
||||||
|
@endif
|
||||||
@stop
|
@stop
|
@ -113,8 +113,6 @@ header h3 em {
|
|||||||
color: #eb8039;
|
color: #eb8039;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.secure {
|
.secure {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
float: right;
|
float: right;
|
||||||
@ -136,6 +134,80 @@ header h3 em {
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#plaid_link_button img {
|
||||||
|
height:30px;
|
||||||
|
vertical-align:-7px;
|
||||||
|
margin-right:5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#plaid_link_button:hover img,
|
||||||
|
#plaid_link_button .hoverimg{
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#plaid_link_button:hover .hoverimg{
|
||||||
|
display:inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#plaid_link_button {
|
||||||
|
width:425px;
|
||||||
|
border-color:#2A5A74;
|
||||||
|
color:#2A5A74;
|
||||||
|
}
|
||||||
|
|
||||||
|
#plaid_link_button:hover {
|
||||||
|
width:425px;
|
||||||
|
background-color:#2A5A74;
|
||||||
|
color:#fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#plaid_or,
|
||||||
|
#plaid_container {
|
||||||
|
text-align:center
|
||||||
|
}
|
||||||
|
|
||||||
|
#plaid_or span{
|
||||||
|
background:#fff;
|
||||||
|
position:relative;
|
||||||
|
bottom:-11px;
|
||||||
|
font-size:125%;
|
||||||
|
padding:0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#plaid_or {
|
||||||
|
border-bottom:1px solid #000;
|
||||||
|
margin:10px 0 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#secured_by_plaid{
|
||||||
|
position:fixed;
|
||||||
|
z-index:999999999;
|
||||||
|
bottom:5px;
|
||||||
|
left:5px;
|
||||||
|
color:#fff;
|
||||||
|
border:1px solid #fff;
|
||||||
|
padding:3px 7px 3px 3px;
|
||||||
|
border-radius:3px;
|
||||||
|
vertical-align:-5px;
|
||||||
|
text-decoration: none!important;
|
||||||
|
}
|
||||||
|
#secured_by_plaid img{
|
||||||
|
height:20px;
|
||||||
|
margin-right:5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#secured_by_plaid:hover{
|
||||||
|
background-color:#2A5A74;
|
||||||
|
}
|
||||||
|
|
||||||
|
#plaid_linked{
|
||||||
|
margin:40px 0;
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#plaid_linked_status {
|
||||||
|
margin-bottom:10px;
|
||||||
|
font-size:150%;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user