diff --git a/app/Models/Gateway.php b/app/Models/Gateway.php index feddf40625de..2c74e118500a 100644 --- a/app/Models/Gateway.php +++ b/app/Models/Gateway.php @@ -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; diff --git a/app/PaymentDrivers/Forte/ACH.php b/app/PaymentDrivers/Forte/ACH.php new file mode 100644 index 000000000000..4795f956d6d0 --- /dev/null +++ b/app/PaymentDrivers/Forte/ACH.php @@ -0,0 +1,150 @@ +forte = $forte; + + $this->forte_base_uri = "https://sandbox.forte.net/api/v3/"; + if($this->forte->company_gateway->getConfigField('testMode') == false){ + $this->forte_base_uri = "https://api.forte.net/v3/"; + } + $this->forte_api_access_id = $this->forte->company_gateway->getConfigField('apiAccessId'); + $this->forte_secure_key = $this->forte->company_gateway->getConfigField('secureKey'); + $this->forte_auth_organization_id = $this->forte->company_gateway->getConfigField('authOrganizationId'); + $this->forte_organization_id = $this->forte->company_gateway->getConfigField('organizationId'); + $this->forte_location_id = $this->forte->company_gateway->getConfigField('locationId'); + } + + public function authorizeView(array $data) + { + return render('gateways.forte.ach.authorize', $data); + } + + public function authorizeResponse(Request $request) + { + + $payment_meta = new \stdClass; + $payment_meta->brand = (string)ctrans('texts.ach'); + $payment_meta->last4 = (string) $request->last_4; + $payment_meta->exp_year = '-'; + $payment_meta->type = GatewayType::BANK_TRANSFER; + + $data = [ + 'payment_meta' => $payment_meta, + 'token' => $request->one_time_token, + 'payment_method_id' => $request->gateway_type_id, + ]; + + $this->forte->storeGatewayToken($data); + + return redirect()->route('client.payment_methods.index')->withSuccess('Payment Method added.'); + } + + 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; + return render('gateways.forte.ach.pay', $data); + } + + public function paymentResponse($request) + { + $payment_hash = PaymentHash::whereRaw('BINARY `hash`= ?', [$request->input('payment_hash')])->firstOrFail(); + + 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": '.$payment_hash->data->total->amount_with_fee.', + "echeck":{ + "sec_code":"PPD", + }, + "billing_address":{ + "first_name": "'.$this->forte->client->name.'", + "last_name": "'.$this->forte->client->name.'" + }, + "echeck":{ + "one_time_token":"'.$request->payment_token.'" + } + }', + 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 = [ + 'payment_method' => $request->payment_method_id, + 'payment_type' => PaymentType::ACH, + 'amount' => $payment_hash->data->amount_with_fee, + 'transaction_reference' => $response->transaction_id, + 'gateway_type_id' => GatewayType::BANK_TRANSFER, + ]; + + $payment=$this->forte->createPayment($data, Payment::STATUS_COMPLETED); + return redirect('client/invoices')->withSuccess('Invoice paid.'); + } +} diff --git a/app/PaymentDrivers/Forte/CreditCard.php b/app/PaymentDrivers/Forte/CreditCard.php new file mode 100644 index 000000000000..b9882b3a4349 --- /dev/null +++ b/app/PaymentDrivers/Forte/CreditCard.php @@ -0,0 +1,160 @@ +forte = $forte; + + $this->forte_base_uri = "https://sandbox.forte.net/api/v3/"; + if($this->forte->company_gateway->getConfigField('testMode') == false){ + $this->forte_base_uri = "https://api.forte.net/v3/"; + } + $this->forte_api_access_id = $this->forte->company_gateway->getConfigField('apiAccessId'); + $this->forte_secure_key = $this->forte->company_gateway->getConfigField('secureKey'); + $this->forte_auth_organization_id = $this->forte->company_gateway->getConfigField('authOrganizationId'); + $this->forte_organization_id = $this->forte->company_gateway->getConfigField('organizationId'); + $this->forte_location_id = $this->forte->company_gateway->getConfigField('locationId'); + } + + public function authorizeView(array $data) + { + return render('gateways.forte.credit_card.authorize', $data); + } + + public function authorizeResponse($request) + { + $payment_meta = new \stdClass; + $payment_meta->exp_month = (string) $request->expire_month; + $payment_meta->exp_year = (string) $request->expire_year; + $payment_meta->brand = (string) $request->card_type; + $payment_meta->last4 = (string) $request->last_4; + $payment_meta->type = GatewayType::CREDIT_CARD; + + $data = [ + 'payment_meta' => $payment_meta, + 'token' => $request->one_time_token, + 'payment_method_id' => $request->payment_method_id, + ]; + + $this->forte->storeGatewayToken($data); + + return redirect()->route('client.payment_methods.index')->withSuccess('Payment Method added.'); + } + + 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; + return render('gateways.forte.credit_card.pay', $data); + } + + public function paymentResponse(PaymentResponseRequest $request) + { + $payment_hash = PaymentHash::whereRaw('BINARY `hash`= ?', [$request->input('payment_hash')])->firstOrFail(); + $amount_with_fee = $payment_hash->data->total->amount_with_fee; + $invoice_totals = $payment_hash->data->total->invoice_totals; + $fee_total = 0; + print_r($payment_hash->data->total); + for ($i = ($invoice_totals * 100) ; $i < ($amount_with_fee * 100); $i++) { + $calculated_fee = ( 3 * $i) / 100; + $calculated_amount_with_fee = round(($i + $calculated_fee) / 100,2); + if ($calculated_amount_with_fee == $amount_with_fee) { + $fee_total = round($calculated_fee / 100,2); + $amount_with_fee = $calculated_amount_with_fee; + break; + } + } + + 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":'.$amount_with_fee.', + "service_fee_amount":'.$fee_total.', + "billing_address":{ + "first_name":"'.$this->forte->client->name.'", + "last_name":"'.$this->forte->client->name.'" + }, + "card":{ + "one_time_token":"'.$request->payment_token.'" + } + }', + CURLOPT_HTTPHEADER => array( + 'Content-Type: application/json', + 'X-Forte-Auth-Organization-Id: '.$this->forte_organization_id, + 'Authorization: Basic '.base64_encode($this->forte_api_access_id.':'.$this->forte_secure_key) + ), + )); + + $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 = [ + 'payment_method' => $request->payment_method_id, + 'payment_type' => PaymentType::parseCardType(strtolower($request->card_brand)) ?: PaymentType::CREDIT_CARD_OTHER, + 'amount' => $payment_hash->data->amount_with_fee, + 'transaction_reference' => $response->transaction_id, + 'gateway_type_id' => GatewayType::CREDIT_CARD, + ]; + $payment=$this->forte->createPayment($data, Payment::STATUS_COMPLETED); + return redirect('client/invoices')->withSuccess('Invoice paid.'); + } +} diff --git a/app/PaymentDrivers/FortePaymentDriver.php b/app/PaymentDrivers/FortePaymentDriver.php new file mode 100644 index 000000000000..e79df1dd96dd --- /dev/null +++ b/app/PaymentDrivers/FortePaymentDriver.php @@ -0,0 +1,90 @@ + 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 + // } +} diff --git a/database/migrations/2022_04_14_121548_forte_payment_gateway.php b/database/migrations/2022_04_14_121548_forte_payment_gateway.php new file mode 100644 index 000000000000..93268ed7ad38 --- /dev/null +++ b/database/migrations/2022_04_14_121548_forte_payment_gateway.php @@ -0,0 +1,50 @@ +testMode = false; + $fields->apiLoginId = ""; + $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() + { + // + } +} diff --git a/database/seeders/PaymentLibrariesSeeder.php b/database/seeders/PaymentLibrariesSeeder.php index 219665df6991..b3a6041e3638 100644 --- a/database/seeders/PaymentLibrariesSeeder.php +++ b/database/seeders/PaymentLibrariesSeeder.php @@ -98,7 +98,7 @@ class PaymentLibrariesSeeder extends Seeder Gateway::query()->update(['visible' => 0]); - Gateway::whereIn('id', [1,3,7,11,15,20,39,46,55,50,57,52,58])->update(['visible' => 1]); + Gateway::whereIn('id', [1,3,7,11,15,20,39,46,55,50,57,52,58,59])->update(['visible' => 1]); if (Ninja::isHosted()) { Gateway::whereIn('id', [20])->update(['visible' => 0]); diff --git a/public/js/clients/payments/forte-ach-payment.js b/public/js/clients/payments/forte-ach-payment.js new file mode 100644 index 000000000000..837aeac0b641 --- /dev/null +++ b/public/js/clients/payments/forte-ach-payment.js @@ -0,0 +1,81 @@ +/******/ (() => { // webpackBootstrap +var __webpack_exports__ = {}; +/*!************************************************************!*\ + !*** ./resources/js/clients/payments/forte-ach-payment.js ***! + \************************************************************/ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * 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 + */ +var ForteAuthorizeACH = function ForteAuthorizeACH(apiLoginId) { + var _this = this; + + _classCallCheck(this, ForteAuthorizeACH); + + _defineProperty(this, "handleAuthorization", function () { + var account_number = document.getElementById('account-number').value; + var routing_number = document.getElementById('routing-number').value; + var data = { + api_login_id: _this.apiLoginId, + account_number: account_number, + routing_number: routing_number, + account_type: 'checking' + }; + var payNowButton = document.getElementById('pay-now'); + + if (payNowButton) { + document.getElementById('pay-now').disabled = true; + document.querySelector('#pay-now > svg').classList.remove('hidden'); + document.querySelector('#pay-now > span').classList.add('hidden'); + } // console.log(data); + + + forte.createToken(data).success(_this.successResponseHandler).error(_this.failedResponseHandler); + return false; + }); + + _defineProperty(this, "successResponseHandler", function (response) { + document.getElementById('payment_token').value = response.onetime_token; + document.getElementById('server_response').submit(); + return false; + }); + + _defineProperty(this, "failedResponseHandler", function (response) { + var errors = '
'; + document.getElementById('forte_errors').innerHTML = errors; + document.getElementById('pay-now').disabled = false; + document.querySelector('#pay-now > svg').classList.add('hidden'); + document.querySelector('#pay-now > span').classList.remove('hidden'); + return false; + }); + + _defineProperty(this, "handle", function () { + var payNowButton = document.getElementById('pay-now'); + + if (payNowButton) { + payNowButton.addEventListener('click', function (e) { + _this.handleAuthorization(); + }); + } + + return _this; + }); + + this.apiLoginId = apiLoginId; +}; + +var apiLoginId = document.querySelector('meta[name="forte-api-login-id"]').content; +/** @handle */ + +new ForteAuthorizeACH(apiLoginId).handle(); +/******/ })() +; \ No newline at end of file diff --git a/public/js/clients/payments/forte-card-js.min.js b/public/js/clients/payments/forte-card-js.min.js new file mode 100644 index 000000000000..833dd5ee4bed --- /dev/null +++ b/public/js/clients/payments/forte-card-js.min.js @@ -0,0 +1,669 @@ +(() => { + function t(t) { + (this.elem = jQuery(t)), + (this.captureName = + !!this.elem.data('capture-name') && + this.elem.data('capture-name')), + (this.iconColour = + !!this.elem.data('icon-colour') && + this.elem.data('icon-colour')), + (this.stripe = + !!this.elem.data('stripe') && this.elem.data('stripe')), + this.stripe && (this.captureName = !1), + this.initCardNumberInput(), + this.initNameInput(), + this.initExpiryMonthInput(), + this.initExpiryYearInput(), + this.initCvcInput(), + this.elem.empty(), + this.setupCardNumberInput(), + this.setupNameInput(), + this.setupExpiryInput(), + this.setupCvcInput(), + this.iconColour && this.setIconColour(this.iconColour), + this.refreshCreditCardTypeIcon(); + } + !(function (e) { + var r = { + init: function () { + return this.data('cardjs', new t(this)), this; + }, + cardNumber: function () { + return this.data('cardjs').getCardNumber(); + }, + cardType: function () { + return this.data('cardjs').getCardType(); + }, + name: function () { + return this.data('cardjs').getName(); + }, + expiryMonth: function () { + return this.data('cardjs').getExpiryMonth(); + }, + expiryYear: function () { + return this.data('cardjs').getExpiryYear(); + }, + cvc: function () { + return this.data('cardjs').getCvc(); + }, + }; + e.fn.CardJs = function (t) { + return r[t] + ? r[t].apply(this, Array.prototype.slice.call(arguments, 1)) + : 'object' != typeof t && t + ? void e.error( + 'Method ' + t + ' does not exist on jQuery.CardJs' + ) + : r.init.apply(this, arguments); + }; + })(jQuery), + $(function () { + $('.card-js').each(function (t, e) { + $(e).CardJs(); + }); + }), + (t.prototype.constructor = t), + (t.KEYS = { + 0: 48, + 9: 57, + NUMPAD_0: 96, + NUMPAD_9: 105, + DELETE: 46, + BACKSPACE: 8, + ARROW_LEFT: 37, + ARROW_RIGHT: 39, + ARROW_UP: 38, + ARROW_DOWN: 40, + HOME: 36, + END: 35, + TAB: 9, + A: 65, + X: 88, + C: 67, + V: 86, + }), + (t.CREDIT_CARD_NUMBER_DEFAULT_MASK = 'XXXX XXXX XXXX XXXX'), + (t.CREDIT_CARD_NUMBER_VISA_MASK = 'XXXX XXXX XXXX XXXX'), + (t.CREDIT_CARD_NUMBER_MASTERCARD_MASK = 'XXXX XXXX XXXX XXXX'), + (t.CREDIT_CARD_NUMBER_DISCOVER_MASK = 'XXXX XXXX XXXX XXXX'), + (t.CREDIT_CARD_NUMBER_JCB_MASK = 'XXXX XXXX XXXX XXXX'), + (t.CREDIT_CARD_NUMBER_AMEX_MASK = 'XXXX XXXXXX XXXXX'), + (t.CREDIT_CARD_NUMBER_DINERS_MASK = 'XXXX XXXX XXXX XX'), + (t.prototype.creditCardNumberMask = t.CREDIT_CARD_NUMBER_DEFAULT_MASK), + (t.CREDIT_CARD_NUMBER_PLACEHOLDER = 'Card number'), + (t.NAME_PLACEHOLDER = 'Name on card'), + (t.EXPIRY_MASK = 'XX / XXXX'), + (t.EXPIRY_PLACEHOLDER = 'MM / YYYY'), + (t.EXPIRY_USE_DROPDOWNS = !1), + (t.EXPIRY_NUMBER_OF_YEARS = 10), + (t.CVC_MASK_3 = 'XXX'), + (t.CVC_MASK_4 = 'XXXX'), + (t.CVC_PLACEHOLDER = 'CVC'), + (t.CREDIT_CARD_SVG = + ''), + (t.LOCK_SVG = + ''), + (t.CALENDAR_SVG = + ''), + (t.USER_SVG = + ''), + (t.MAIL_SVG = + ''), + (t.INFORMATION_SVG = + ''), + (t.keyCodeFromEvent = function (t) { + return t.which || t.keyCode; + }), + (t.keyIsCommandFromEvent = function (t) { + return t.ctrlKey || t.metaKey; + }), + (t.keyIsNumber = function (e) { + return t.keyIsTopNumber(e) || t.keyIsKeypadNumber(e); + }), + (t.keyIsTopNumber = function (e) { + var r = t.keyCodeFromEvent(e); + return r >= t.KEYS[0] && r <= t.KEYS[9]; + }), + (t.keyIsKeypadNumber = function (e) { + var r = t.keyCodeFromEvent(e); + return r >= t.KEYS.NUMPAD_0 && r <= t.KEYS.NUMPAD_9; + }), + (t.keyIsDelete = function (e) { + return t.keyCodeFromEvent(e) == t.KEYS.DELETE; + }), + (t.keyIsBackspace = function (e) { + return t.keyCodeFromEvent(e) == t.KEYS.BACKSPACE; + }), + (t.keyIsDeletion = function (e) { + return t.keyIsDelete(e) || t.keyIsBackspace(e); + }), + (t.keyIsArrow = function (e) { + var r = t.keyCodeFromEvent(e); + return r >= t.KEYS.ARROW_LEFT && r <= t.KEYS.ARROW_DOWN; + }), + (t.keyIsNavigation = function (e) { + var r = t.keyCodeFromEvent(e); + return r == t.KEYS.HOME || r == t.KEYS.END; + }), + (t.keyIsKeyboardCommand = function (e) { + var r = t.keyCodeFromEvent(e); + return ( + t.keyIsCommandFromEvent(e) && + (r == t.KEYS.A || + r == t.KEYS.X || + r == t.KEYS.C || + r == t.KEYS.V) + ); + }), + (t.keyIsTab = function (e) { + return t.keyCodeFromEvent(e) == t.KEYS.TAB; + }), + (t.copyAllElementAttributes = function (t, e) { + $.each(t[0].attributes, function (t, r) { + e.attr(r.nodeName, r.nodeValue); + }); + }), + (t.numbersOnlyString = function (t) { + for (var e = '', r = 0; r < t.length; r++) { + var n = t.charAt(r); + !isNaN(parseInt(n)) && (e += n); + } + return e; + }), + (t.applyFormatMask = function (t, e) { + for (var r = '', n = 0, i = 0; i < e.length; i++) { + var a = e[i]; + if ('X' == a) { + if (!t.charAt(n)) break; + (r += t.charAt(n)), n++; + } else r += a; + } + return r; + }), + (t.cardTypeFromNumber = function (t) { + if (((e = new RegExp('^30[0-5]')), null != t.match(e))) + return 'Diners - Carte Blanche'; + if (((e = new RegExp('^(30[6-9]|36|38)')), null != t.match(e))) + return 'Diners'; + if (((e = new RegExp('^35(2[89]|[3-8][0-9])')), null != t.match(e))) + return 'JCB'; + if (((e = new RegExp('^3[47]')), null != t.match(e))) return 'AMEX'; + if ( + ((e = new RegExp('^(4026|417500|4508|4844|491(3|7))')), + null != t.match(e)) + ) + return 'Visa Electron'; + var e = new RegExp('^4'); + return null != t.match(e) + ? 'Visa' + : ((e = new RegExp('^5[1-5]')), + null != t.match(e) + ? 'Mastercard' + : ((e = new RegExp( + '^(6011|622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5]|64[4-9])|65)' + )), + null != t.match(e) ? 'Discover' : '')); + }), + (t.caretStartPosition = function (t) { + return 'number' == typeof t.selectionStart && t.selectionStart; + }), + (t.caretEndPosition = function (t) { + return 'number' == typeof t.selectionEnd && t.selectionEnd; + }), + (t.setCaretPosition = function (t, e) { + if (null != t) + if (t.createTextRange) { + var r = t.createTextRange(); + r.move('character', e), r.select(); + } else + t.selectionStart + ? (t.focus(), t.setSelectionRange(e, e)) + : t.focus(); + }), + (t.normaliseCaretPosition = function (t, e) { + var r = 0; + if (0 > e || e > t.length) return 0; + for (var n = 0; n < t.length; n++) { + if (n == e) return r; + 'X' == t[n] && r++; + } + return r; + }), + (t.denormaliseCaretPosition = function (t, e) { + var r = 0; + if (0 > e || e > t.length) return 0; + for (var n = 0; n < t.length; n++) { + if (r == e) return n; + 'X' == t[n] && r++; + } + return t.length; + }), + (t.filterNumberOnlyKey = function (e) { + var r = t.keyIsNumber(e), + n = t.keyIsDeletion(e), + i = t.keyIsArrow(e), + a = t.keyIsNavigation(e), + s = t.keyIsKeyboardCommand(e), + p = t.keyIsTab(e); + r || n || i || a || s || p || e.preventDefault(); + }), + (t.digitFromKeyCode = function (e) { + return e >= t.KEYS[0] && e <= t.KEYS[9] + ? e - t.KEYS[0] + : e >= t.KEYS.NUMPAD_0 && e <= t.KEYS.NUMPAD_9 + ? e - t.KEYS.NUMPAD_0 + : null; + }), + (t.handleMaskedNumberInputKey = function (e, r) { + t.filterNumberOnlyKey(e); + var n = e.which || e.keyCode, + i = e.target, + a = t.caretStartPosition(i), + s = t.caretEndPosition(i), + p = t.normaliseCaretPosition(r, a), + c = t.normaliseCaretPosition(r, s), + o = a, + u = t.keyIsNumber(e), + h = t.keyIsDelete(e), + d = t.keyIsBackspace(e); + if (u || h || d) { + e.preventDefault(); + var l = $(i).val(), + y = t.numbersOnlyString(l), + m = t.digitFromKeyCode(n), + C = c > p; + C && (y = y.slice(0, p) + y.slice(c)), + a != r.length && + (u && + l.length <= r.length && + ((y = y.slice(0, p) + m + y.slice(p)), + (o = Math.max( + t.denormaliseCaretPosition(r, p + 1), + t.denormaliseCaretPosition(r, p + 2) - 1 + ))), + h && (y = y.slice(0, p) + y.slice(p + 1))), + 0 != a && + d && + !C && + ((y = y.slice(0, p - 1) + y.slice(p)), + (o = t.denormaliseCaretPosition(r, p - 1))), + $(i).val(t.applyFormatMask(y, r)), + t.setCaretPosition(i, o); + } + }), + (t.handleCreditCardNumberKey = function (e, r) { + t.handleMaskedNumberInputKey(e, r); + }), + (t.handleCreditCardNumberChange = function (t) {}), + (t.handleExpiryKey = function (e) { + t.handleMaskedNumberInputKey(e, t.EXPIRY_MASK); + }), + (t.prototype.getCardNumber = function () { + return this.cardNumberInput.val(); + }), + (t.prototype.getCardType = function () { + return t.cardTypeFromNumber(this.getCardNumber()); + }), + (t.prototype.getName = function () { + return this.nameInput.val(); + }), + (t.prototype.getExpiryMonth = function () { + return this.expiryMonthInput.val(); + }), + (t.prototype.getExpiryYear = function () { + return this.expiryYearInput.val(); + }), + (t.prototype.getCvc = function () { + return this.cvcInput.val(); + }), + (t.prototype.setIconColour = function (t) { + this.elem.find('.icon .svg').css({ fill: t }); + }), + (t.prototype.setIconColour = function (t) { + this.elem.find('.icon .svg').css({ fill: t }); + }), + (t.prototype.refreshCreditCardTypeIcon = function () { + this.setCardTypeIconFromNumber( + t.numbersOnlyString(this.cardNumberInput.val()) + ); + }), + (t.prototype.clearCardTypeIcon = function () { + this.elem + .find('.card-number-wrapper .card-type-icon') + .removeClass('show'); + }), + (t.prototype.setCardTypeIconAsVisa = function () { + this.elem + .find('.card-number-wrapper .card-type-icon') + .attr('class', 'card-type-icon show visa'); + }), + (t.prototype.setCardTypeIconAsMasterCard = function () { + this.elem + .find('.card-number-wrapper .card-type-icon') + .attr('class', 'card-type-icon show master-card'); + }), + (t.prototype.setCardTypeIconAsAmericanExpress = function () { + this.elem + .find('.card-number-wrapper .card-type-icon') + .attr('class', 'card-type-icon show american-express'); + }), + (t.prototype.setCardTypeIconAsDiscover = function () { + this.elem + .find('.card-number-wrapper .card-type-icon') + .attr('class', 'card-type-icon show discover'); + }), + (t.prototype.setCardTypeIconAsDiners = function () { + this.elem + .find('.card-number-wrapper .card-type-icon') + .attr('class', 'card-type-icon show diners'); + }), + (t.prototype.setCardTypeIconAsJcb = function () { + this.elem + .find('.card-number-wrapper .card-type-icon') + .attr('class', 'card-type-icon show jcb'); + }), + (t.prototype.setCardTypeIconFromNumber = function (e) { + switch (t.cardTypeFromNumber(e)) { + case 'Visa Electron': + case 'Visa': + this.setCardTypeAsVisa(); + break; + case 'Mastercard': + this.setCardTypeAsMasterCard(); + break; + case 'AMEX': + this.setCardTypeAsAmericanExpress(); + break; + case 'Discover': + this.setCardTypeAsDiscover(); + break; + case 'Diners - Carte Blanche': + case 'Diners': + this.setCardTypeAsDiners(); + break; + case 'JCB': + this.setCardTypeAsJcb(); + break; + default: + this.clearCardType(); + } + }), + (t.prototype.setCardMask = function (t) { + (this.creditCardNumberMask = t), + this.cardNumberInput.attr('maxlength', t.length); + }), + (t.prototype.setCvc3 = function () { + this.cvcInput.attr('maxlength', t.CVC_MASK_3.length); + }), + (t.prototype.setCvc4 = function () { + this.cvcInput.attr('maxlength', t.CVC_MASK_4.length); + }), + (t.prototype.clearCardType = function () { + this.clearCardTypeIcon(), + this.setCardMask(t.CREDIT_CARD_NUMBER_DEFAULT_MASK), + this.setCvc3(); + }), + (t.prototype.setCardTypeAsVisa = function () { + this.setCardTypeIconAsVisa(), + this.setCardMask(t.CREDIT_CARD_NUMBER_VISA_MASK), + this.setCvc3(); + }), + (t.prototype.setCardTypeAsMasterCard = function () { + this.setCardTypeIconAsMasterCard(), + this.setCardMask(t.CREDIT_CARD_NUMBER_MASTERCARD_MASK), + this.setCvc3(); + }), + (t.prototype.setCardTypeAsAmericanExpress = function () { + this.setCardTypeIconAsAmericanExpress(), + this.setCardMask(t.CREDIT_CARD_NUMBER_AMEX_MASK), + this.setCvc4(); + }), + (t.prototype.setCardTypeAsDiscover = function () { + this.setCardTypeIconAsDiscover(), + this.setCardMask(t.CREDIT_CARD_NUMBER_DISCOVER_MASK), + this.setCvc3(); + }), + (t.prototype.setCardTypeAsDiners = function () { + this.setCardTypeIconAsDiners(), + this.setCardMask(t.CREDIT_CARD_NUMBER_DINERS_MASK), + this.setCvc3(); + }), + (t.prototype.setCardTypeAsJcb = function () { + this.setCardTypeIconAsJcb(), + this.setCardMask(t.CREDIT_CARD_NUMBER_JCB_MASK), + this.setCvc3(); + }), + (t.prototype.initCardNumberInput = function () { + var e = this; + (this.cardNumberInput = this.elem.find('.card-number')), + this.cardNumberInput[0] + ? this.cardNumberInput.detach() + : (this.cardNumberInput = $( + "" + )), + this.cardNumberInput.attr('type', 'tel'), + this.cardNumberInput.attr('placeholder') || + this.cardNumberInput.attr( + 'placeholder', + t.CREDIT_CARD_NUMBER_PLACEHOLDER + ), + this.cardNumberInput.attr( + 'maxlength', + this.creditCardNumberMask.length + ), + this.cardNumberInput.attr('x-autocompletetype', 'cc-number'), + this.cardNumberInput.attr('autocompletetype', 'cc-number'), + this.cardNumberInput.attr('autocorrect', 'off'), + this.cardNumberInput.attr('spellcheck', 'off'), + this.cardNumberInput.attr('autocapitalize', 'off'), + this.cardNumberInput.keydown(function (r) { + t.handleCreditCardNumberKey(r, e.creditCardNumberMask); + }), + this.cardNumberInput.keyup(function (t) { + e.refreshCreditCardTypeIcon(); + }), + this.cardNumberInput.change(t.handleCreditCardNumberChange); + }), + (t.prototype.initNameInput = function () { + (this.nameInput = this.elem.find('.name')), + this.nameInput[0] + ? ((this.captureName = !0), this.nameInput.detach()) + : (this.nameInput = $("")), + this.nameInput.attr('placeholder') || + this.nameInput.attr('placeholder', t.NAME_PLACEHOLDER); + }), + (t.prototype.initExpiryMonthInput = function () { + (this.expiryMonthInput = this.elem.find('.expiry-month')), + this.expiryMonthInput[0] + ? this.expiryMonthInput.detach() + : (this.expiryMonthInput = $( + "" + )); + }), + (t.prototype.initExpiryYearInput = function () { + (this.expiryYearInput = this.elem.find('.expiry-year')), + this.expiryYearInput[0] + ? this.expiryYearInput.detach() + : (this.expiryYearInput = $( + "" + )); + }), + (t.prototype.initCvcInput = function () { + (this.cvcInput = this.elem.find('.cvc')), + this.cvcInput[0] + ? this.cvcInput.detach() + : (this.cvcInput = $("")), + this.cvcInput.attr('type', 'tel'), + this.cvcInput.attr('placeholder') || + this.cvcInput.attr('placeholder', t.CVC_PLACEHOLDER), + this.cvcInput.attr('maxlength', t.CVC_MASK_3.length), + this.cvcInput.attr('x-autocompletetype', 'cc-csc'), + this.cvcInput.attr('autocompletetype', 'cc-csc'), + this.cvcInput.attr('autocorrect', 'off'), + this.cvcInput.attr('spellcheck', 'off'), + this.cvcInput.attr('autocapitalize', 'off'), + this.cvcInput.keydown(t.filterNumberOnlyKey); + }), + (t.prototype.setupCardNumberInput = function () { + this.stripe && this.cardNumberInput.attr('data-stripe', 'number'), + this.elem.append("
"); + var e = this.elem.find('.card-number-wrapper'); + e.append(this.cardNumberInput), + e.append("
"), + e.append("
"), + e.find('.icon').append(t.CREDIT_CARD_SVG); + }), + (t.prototype.setupNameInput = function () { + if (this.captureName) { + this.elem.append("
"); + var e = this.elem.find('.name-wrapper'); + e.append(this.nameInput), + e.append("
"), + e.find('.icon').append(t.USER_SVG); + } + }), + (t.prototype.setupExpiryInput = function () { + this.elem.append( + "
" + ); + var e, + r = this.elem.find('.expiry-wrapper'); + if (this.EXPIRY_USE_DROPDOWNS) { + e = $('
'); + var n = $( + "" + ), + i = this.expiryMonthInput; + t.copyAllElementAttributes(i, n), + this.expiryMonthInput.remove(), + (this.expiryMonthInput = n); + for ( + var a = $( + "" + ), + s = parseInt( + new Date().getFullYear().toString().substring(2, 4) + ), + p = 0; + p < t.EXPIRY_NUMBER_OF_YEARS; + p++ + ) + a.append("'), + (s = (s + 1) % 100); + var c = this.expiryYearInput; + t.copyAllElementAttributes(c, a), + this.expiryYearInput.remove(), + (this.expiryYearInput = a), + e.append(this.expiryMonthInput), + e.append(this.expiryYearInput); + } else { + (e = $('
')), + (this.expiryMonthInput = $( + "" + )), + (this.expiryYearInput = $( + "" + )), + this.stripe && + (this.expiryMonthInput.attr('data-stripe', 'exp-month'), + this.expiryYearInput.attr('data-stripe', 'exp-year')), + (this.expiryMonthYearInput = $("")), + this.expiryMonthYearInput.attr('type', 'tel'), + this.expiryMonthYearInput.attr('placeholder') || + this.expiryMonthYearInput.attr( + 'placeholder', + t.EXPIRY_PLACEHOLDER + ), + this.expiryMonthYearInput.attr( + 'maxlength', + t.EXPIRY_MASK.length + ), + this.expiryMonthYearInput.attr( + 'x-autocompletetype', + 'cc-exp' + ), + this.expiryMonthYearInput.attr( + 'autocompletetype', + 'cc-exp' + ), + this.expiryMonthYearInput.attr('autocorrect', 'off'), + this.expiryMonthYearInput.attr('spellcheck', 'off'), + this.expiryMonthYearInput.attr('autocapitalize', 'off'); + var o = this; + this.expiryMonthYearInput.keydown(function (e) { + t.handleExpiryKey(e); + var r = o.expiryMonthYearInput.val(); + 1 == r.length && + parseInt(r) > 1 && + t.keyIsNumber(e) && + o.expiryMonthYearInput.val( + t.applyFormatMask('0' + r, t.EXPIRY_MASK) + ), + o.EXPIRY_USE_DROPDOWNS || + null == o.expiryMonthYearInput || + (o.expiryMonthInput.val(o.expiryMonth()), + o.expiryYearInput.val( + 9 == r.length ? r.substr(5, 4) : null + )); + }), + this.expiryMonthYearInput.blur(function (t) { + o.refreshExpiryMonthValidation(); + }), + e.append(this.expiryMonthYearInput), + e.append(this.expiryMonthInput), + e.append(this.expiryYearInput); + } + r.append(e), + r.append("
"), + r.find('.icon').append(t.CALENDAR_SVG); + }), + (t.prototype.setupCvcInput = function () { + this.stripe && this.cvcInput.attr('data-stripe', 'cvc'), + this.elem.append( + "
" + ); + var e = this.elem.find('.cvc-wrapper'); + e.append(this.cvcInput), + e.append("
"), + e.find('.icon').append(t.LOCK_SVG); + }), + (t.prototype.expiryMonth = function () { + if ( + !this.EXPIRY_USE_DROPDOWNS && + null != this.expiryMonthYearInput + ) { + var t = this.expiryMonthYearInput.val(); + return t.length >= 2 ? parseInt(t.substr(0, 2)) : null; + } + return null; + }), + (t.isValidMonth = function (t) { + return t >= 1 && 12 >= t; + }), + (t.isExpiryValid = function (e, r) { + var n = new Date(), + i = n.getMonth() + 1, + a = '' + n.getFullYear(); + return ( + 2 == ('' + r).length && (r = a.substring(0, 2) + '' + r), + (i = parseInt(i)), + (a = parseInt(a)), + (e = parseInt(e)), + (r = parseInt(r)), + t.isValidMonth(e) && (r > a || (r == a && e >= i)) + ); + }), + (t.prototype.refreshExpiryMonthValidation = function () { + t.isExpiryValid(this.getExpiryMonth(), this.getExpiryYear()) + ? this.setExpiryMonthAsValid() + : this.setExpiryMonthAsInvalid(); + }), + (t.prototype.setExpiryMonthAsValid = function () { + this.EXPIRY_USE_DROPDOWNS || + this.expiryMonthYearInput.parent().removeClass('has-error'); + }), + (t.prototype.setExpiryMonthAsInvalid = function () { + this.EXPIRY_USE_DROPDOWNS || + this.expiryMonthYearInput.parent().addClass('has-error'); + }); +})(); diff --git a/public/js/clients/payments/forte-credit-card-payment.js b/public/js/clients/payments/forte-credit-card-payment.js new file mode 100644 index 000000000000..2c181f59171d --- /dev/null +++ b/public/js/clients/payments/forte-credit-card-payment.js @@ -0,0 +1,82 @@ +/******/ (() => { // webpackBootstrap +var __webpack_exports__ = {}; +/*!********************************************************************!*\ + !*** ./resources/js/clients/payments/forte-credit-card-payment.js ***! + \********************************************************************/ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * 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 + */ +var ForteAuthorizeCard = function ForteAuthorizeCard(apiLoginId) { + var _this = this; + + _classCallCheck(this, ForteAuthorizeCard); + + _defineProperty(this, "handleAuthorization", function () { + var myCard = $('#my-card'); + var data = { + api_login_id: _this.apiLoginId, + card_number: myCard.CardJs('cardNumber').replace(/[^\d]/g, ''), + expire_year: myCard.CardJs('expiryYear').replace(/[^\d]/g, ''), + expire_month: myCard.CardJs('expiryMonth').replace(/[^\d]/g, ''), + cvv: document.getElementById('cvv').value.replace(/[^\d]/g, '') + }; + var payNowButton = document.getElementById('pay-now'); + + if (payNowButton) { + document.getElementById('pay-now').disabled = true; + document.querySelector('#pay-now > svg').classList.remove('hidden'); + document.querySelector('#pay-now > span').classList.add('hidden'); + } + + forte.createToken(data).success(_this.successResponseHandler).error(_this.failedResponseHandler); + return false; + }); + + _defineProperty(this, "successResponseHandler", function (response) { + document.getElementById('payment_token').value = response.onetime_token; + document.getElementById('card_brand').value = response.card_type; + document.getElementById('server_response').submit(); + return false; + }); + + _defineProperty(this, "failedResponseHandler", function (response) { + var errors = '
'; + document.getElementById('forte_errors').innerHTML = errors; + document.getElementById('pay-now').disabled = false; + document.querySelector('#pay-now > svg').classList.add('hidden'); + document.querySelector('#pay-now > span').classList.remove('hidden'); + return false; + }); + + _defineProperty(this, "handle", function () { + var payNowButton = document.getElementById('pay-now'); + + if (payNowButton) { + payNowButton.addEventListener('click', function (e) { + _this.handleAuthorization(); + }); + } + + return _this; + }); + + this.apiLoginId = apiLoginId; + this.cardHolderName = document.getElementById('cardholder_name'); +}; + +var apiLoginId = document.querySelector('meta[name="forte-api-login-id"]').content; +/** @handle */ + +new ForteAuthorizeCard(apiLoginId).handle(); +/******/ })() +; \ No newline at end of file diff --git a/resources/js/clients/payments/forte-ach-payment.js b/resources/js/clients/payments/forte-ach-payment.js new file mode 100644 index 000000000000..90bf9f675377 --- /dev/null +++ b/resources/js/clients/payments/forte-ach-payment.js @@ -0,0 +1,81 @@ +/** + * 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 + */ + +class ForteAuthorizeACH { + constructor(apiLoginId) { + this.apiLoginId = apiLoginId; + } + + handleAuthorization = () => { + var account_number = document.getElementById('account-number').value; + var routing_number = document.getElementById('routing-number').value; + + var data = { + api_login_id: this.apiLoginId, + account_number: account_number, + routing_number: routing_number, + account_type: 'checking', + }; + + let payNowButton = document.getElementById('pay-now'); + + if (payNowButton) { + document.getElementById('pay-now').disabled = true; + document.querySelector('#pay-now > svg').classList.remove('hidden'); + document.querySelector('#pay-now > span').classList.add('hidden'); + } + // console.log(data); + forte + .createToken(data) + .success(this.successResponseHandler) + .error(this.failedResponseHandler); + return false; + }; + + successResponseHandler = (response) => { + document.getElementById('payment_token').value = response.onetime_token; + + document.getElementById('server_response').submit(); + + return false; + }; + + failedResponseHandler = (response) => { + var errors = + '
'; + document.getElementById('forte_errors').innerHTML = errors; + document.getElementById('pay-now').disabled = false; + document.querySelector('#pay-now > svg').classList.add('hidden'); + document.querySelector('#pay-now > span').classList.remove('hidden'); + + return false; + }; + + handle = () => { + let payNowButton = document.getElementById('pay-now'); + + if (payNowButton) { + payNowButton.addEventListener('click', (e) => { + this.handleAuthorization(); + }); + } + + return this; + }; +} + +const apiLoginId = document.querySelector( + 'meta[name="forte-api-login-id"]' +).content; + +/** @handle */ +new ForteAuthorizeACH(apiLoginId).handle(); diff --git a/resources/js/clients/payments/forte-credit-card-payment.js b/resources/js/clients/payments/forte-credit-card-payment.js new file mode 100644 index 000000000000..0139356a4daa --- /dev/null +++ b/resources/js/clients/payments/forte-credit-card-payment.js @@ -0,0 +1,83 @@ +/** + * 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 + */ + +class ForteAuthorizeCard { + constructor(apiLoginId) { + this.apiLoginId = apiLoginId; + this.cardHolderName = document.getElementById('cardholder_name'); + } + + handleAuthorization = () => { + var myCard = $('#my-card'); + + var data = { + api_login_id: this.apiLoginId, + card_number: myCard.CardJs('cardNumber').replace(/[^\d]/g, ''), + expire_year: myCard.CardJs('expiryYear').replace(/[^\d]/g, ''), + expire_month: myCard.CardJs('expiryMonth').replace(/[^\d]/g, ''), + cvv: document.getElementById('cvv').value.replace(/[^\d]/g, ''), + }; + + let payNowButton = document.getElementById('pay-now'); + + if (payNowButton) { + document.getElementById('pay-now').disabled = true; + document.querySelector('#pay-now > svg').classList.remove('hidden'); + document.querySelector('#pay-now > span').classList.add('hidden'); + } + + forte + .createToken(data) + .success(this.successResponseHandler) + .error(this.failedResponseHandler); + return false; + }; + + successResponseHandler = (response) => { + document.getElementById('payment_token').value = response.onetime_token; + document.getElementById('card_brand').value = response.card_type; + + document.getElementById('server_response').submit(); + + return false; + }; + + failedResponseHandler = (response) => { + var errors = + '
'; + document.getElementById('forte_errors').innerHTML = errors; + document.getElementById('pay-now').disabled = false; + document.querySelector('#pay-now > svg').classList.add('hidden'); + document.querySelector('#pay-now > span').classList.remove('hidden'); + + return false; + }; + + handle = () => { + let payNowButton = document.getElementById('pay-now'); + + if (payNowButton) { + payNowButton.addEventListener('click', (e) => { + this.handleAuthorization(); + }); + } + + return this; + }; +} + +const apiLoginId = document.querySelector( + 'meta[name="forte-api-login-id"]' +).content; + +/** @handle */ +new ForteAuthorizeCard(apiLoginId).handle(); diff --git a/resources/views/portal/ninja2020/gateways/forte/ach/authorize.blade.php b/resources/views/portal/ninja2020/gateways/forte/ach/authorize.blade.php new file mode 100644 index 000000000000..6929c8b3ea8b --- /dev/null +++ b/resources/views/portal/ninja2020/gateways/forte/ach/authorize.blade.php @@ -0,0 +1,131 @@ +@extends('portal.ninja2020.layout.payments', ['gateway_title' => 'Bank Details', 'card_title' => 'Bank Details']) + +@section('gateway_head') + @if($gateway->getConfigField('testMode')) + + @else + + @endif +@endsection + +@section('gateway_content') + @if(session()->has('ach_error')) +
+

{{ session('ach_error') }}

+
+ @endif + @if(Session::has('error')) +
{{ Session::get('error') }}
+ @endif +
+ @if ($errors->any()) +
+ +
+ @endif + +
+ @csrf + + + + + + + + + + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.account_holder_type')]) + + + {{ __('texts.individual_account') }} + + + + {{ __('texts.company_account') }} + + @endcomponent + + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.account_holder_name')]) + + @endcomponent + + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.country')]) + + @endcomponent + + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.currency')]) + + @endcomponent + + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.routing_number')]) + + @endcomponent + + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.account_number')]) + + @endcomponent + + @component('portal.ninja2020.components.general.card-element-single') + + + @endcomponent + +
+ + +
+
+ +@endsection + +@section('gateway_footer') + +@endsection diff --git a/resources/views/portal/ninja2020/gateways/forte/ach/pay.blade.php b/resources/views/portal/ninja2020/gateways/forte/ach/pay.blade.php new file mode 100644 index 000000000000..5dbb93fbd246 --- /dev/null +++ b/resources/views/portal/ninja2020/gateways/forte/ach/pay.blade.php @@ -0,0 +1,53 @@ +@extends('portal.ninja2020.layout.payments', ['gateway_title' => 'Bank Transfer', 'card_title' => 'Bank Transfer']) + +@section('gateway_head') + +@endsection + +@section('gateway_content') +
+ @csrf + + + + + + + + + +
+ +
+ + @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' => 'Pay with Bank Transfer']) + +
+ +
+
+ +
+ @endcomponent + + @include('portal.ninja2020.gateways.includes.pay_now') + +@endsection + +@section('gateway_footer') + @if($gateway->forte->company_gateway->getConfigField('testMode')) + + @else + + @endif + + +@endsection diff --git a/resources/views/portal/ninja2020/gateways/forte/credit_card/authorize.blade.php b/resources/views/portal/ninja2020/gateways/forte/credit_card/authorize.blade.php new file mode 100644 index 000000000000..70d356f8e2f2 --- /dev/null +++ b/resources/views/portal/ninja2020/gateways/forte/credit_card/authorize.blade.php @@ -0,0 +1,122 @@ +@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.credit_card'), 'card_title' => ctrans('texts.credit_card')]) + +@section('gateway_head') + + + + + + + + + @if($gateway->getConfigField('testMode')) + + @else + + @endif +@endsection + +@section('gateway_content') +
+ @csrf + + + + + + + + + @if(!Request::isSecure()) +

{{ ctrans('texts.https_required') }}

+ @endif + + + @if(Session::has('error')) +
{{ Session::get('error') }}
+ @endif +
+ @if ($errors->any()) +
+ +
+ @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') + +
+ + +
+ +
+@endsection + +@section('gateway_footer') + +@endsection \ No newline at end of file diff --git a/resources/views/portal/ninja2020/gateways/forte/credit_card/pay.blade.php b/resources/views/portal/ninja2020/gateways/forte/credit_card/pay.blade.php new file mode 100644 index 000000000000..1cceb137f39c --- /dev/null +++ b/resources/views/portal/ninja2020/gateways/forte/credit_card/pay.blade.php @@ -0,0 +1,51 @@ +@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' => ctrans('texts.payment_type_credit_card')]) + +@section('gateway_head') + + + + + +@endsection + +@section('gateway_content') +
+ @csrf + + + + + + + + + + + +
+ +
+ + @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' => 'Pay with Credit Card']) + @include('portal.ninja2020.gateways.forte.includes.credit_card') + @endcomponent + + @include('portal.ninja2020.gateways.includes.pay_now') + +@endsection + +@section('gateway_footer') + @if($gateway->forte->company_gateway->getConfigField('testMode')) + + @else + + @endif + + +@endsection diff --git a/resources/views/portal/ninja2020/gateways/forte/includes/credit_card.blade.php b/resources/views/portal/ninja2020/gateways/forte/includes/credit_card.blade.php new file mode 100644 index 000000000000..5183e72986ed --- /dev/null +++ b/resources/views/portal/ninja2020/gateways/forte/includes/credit_card.blade.php @@ -0,0 +1,12 @@ +
+
+ + + + + +
+ +
+
diff --git a/webpack.mix.js b/webpack.mix.js index 926ac4b4000a..2ed78e49227c 100644 --- a/webpack.mix.js +++ b/webpack.mix.js @@ -10,6 +10,14 @@ mix.js("resources/js/app.js", "public/js") "resources/js/clients/payments/authorize-credit-card-payment.js", "public/js/clients/payments/authorize-credit-card-payment.js" ) + .js( + "resources/js/clients/payments/forte-credit-card-payment.js", + "public/js/clients/payments/forte-credit-card-payment.js" + ) + .js( + "resources/js/clients/payments/forte-ach-payment.js", + "public/js/clients/payments/forte-ach-payment.js" + ) .js( "resources/js/clients/payments/stripe-ach.js", "public/js/clients/payments/stripe-ach.js"