mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-08 05:24:29 -04:00
merge
This commit is contained in:
commit
20b04a266f
@ -17,7 +17,7 @@ use App\Models\Subscription;
|
|||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
|
||||||
class Methods extends Component
|
class Methods extends Component
|
||||||
{
|
{//@todo this breaks down when the cart is in front of the login - we have no context on the user - nor their country/currency
|
||||||
public Subscription $subscription;
|
public Subscription $subscription;
|
||||||
|
|
||||||
public array $context;
|
public array $context;
|
||||||
@ -28,10 +28,7 @@ class Methods extends Component
|
|||||||
{
|
{
|
||||||
$total = collect($this->context['products'])->sum('total_raw');
|
$total = collect($this->context['products'])->sum('total_raw');
|
||||||
|
|
||||||
$methods = auth()->guard('contact')->user()->client->service()->getPaymentMethods(
|
$methods = auth()->guard('contact')->user()->client->service()->getPaymentMethods($total); //@todo this breaks down when the cart is in front of the login - we have no context on the user - nor their country/currency()
|
||||||
$total,
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->methods = $methods;
|
$this->methods = $methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,6 +199,7 @@ class BillingPortalPurchasev2 extends Component
|
|||||||
$this->data = [];
|
$this->data = [];
|
||||||
|
|
||||||
$this->price = $this->subscription->price; // ?
|
$this->price = $this->subscription->price; // ?
|
||||||
|
$this->float_amount_total = $this->price;
|
||||||
|
|
||||||
$this->recurring_products = $this->subscription->service()->recurring_products();
|
$this->recurring_products = $this->subscription->service()->recurring_products();
|
||||||
$this->products = $this->subscription->service()->products();
|
$this->products = $this->subscription->service()->products();
|
||||||
@ -244,7 +245,8 @@ class BillingPortalPurchasev2 extends Component
|
|||||||
Auth::guard('contact')->loginUsingId($contact->id, true);
|
Auth::guard('contact')->loginUsingId($contact->id, true);
|
||||||
$this->contact = $contact;
|
$this->contact = $contact;
|
||||||
} else {
|
} else {
|
||||||
$this->createClientContact();
|
// $this->createClientContact();
|
||||||
|
$this->createBlankClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->getPaymentMethods();
|
$this->getPaymentMethods();
|
||||||
@ -767,6 +769,8 @@ class BillingPortalPurchasev2 extends Component
|
|||||||
if ($currency) {
|
if ($currency) {
|
||||||
$data['settings']->currency_id = $currency->id;
|
$data['settings']->currency_id = $currency->id;
|
||||||
}
|
}
|
||||||
|
}else {
|
||||||
|
$data['settings']->currency_id = $this->subscription->company->getSetting('currency_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array_key_exists('locale', $this->request_data)) {
|
if (array_key_exists('locale', $this->request_data)) {
|
||||||
@ -785,8 +789,12 @@ class BillingPortalPurchasev2 extends Component
|
|||||||
}
|
}
|
||||||
|
|
||||||
$client = $client_repo->save($data, ClientFactory::create($company->id, $user->id));
|
$client = $client_repo->save($data, ClientFactory::create($company->id, $user->id));
|
||||||
|
$contact = $client->fresh()->contacts->first();
|
||||||
|
$this->contact = $contact;
|
||||||
|
|
||||||
return $client->fresh()->contacts->first();
|
Auth::guard('contact')->loginUsingId($contact->id, true);
|
||||||
|
|
||||||
|
return $contact;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,11 +52,11 @@ class UnderOverPayment extends Component
|
|||||||
|
|
||||||
$input_amount = collect($payableInvoices)->sum('amount');
|
$input_amount = collect($payableInvoices)->sum('amount');
|
||||||
|
|
||||||
if($settings->client_portal_allow_under_payment && $settings->client_portal_under_payment_minimum != 0)
|
if($settings->client_portal_allow_under_payment)
|
||||||
{
|
{
|
||||||
if($input_amount <= $settings->client_portal_under_payment_minimum){
|
if($input_amount <= $settings->client_portal_under_payment_minimum || $input_amount <= 0){
|
||||||
// return error message under payment too low.
|
// return error message under payment too low.
|
||||||
$this->errors = ctrans('texts.minimum_required_payment', ['amount' => $settings->client_portal_under_payment_minimum]);
|
$this->errors = ctrans('texts.minimum_required_payment', ['amount' => max($settings->client_portal_under_payment_minimum, 1)]);
|
||||||
$this->dispatch('errorMessageUpdate', errors: $this->errors);
|
$this->dispatch('errorMessageUpdate', errors: $this->errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,13 +194,14 @@ class RequiredClientInfo extends Component
|
|||||||
|
|
||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
|
|
||||||
MultiDB::setDb($this->db);
|
MultiDB::setDb($this->db);
|
||||||
|
|
||||||
$contact = ClientContact::withTrashed()->with(['client' => function ($query) {
|
$contact = ClientContact::withTrashed()->with(['client' => function ($query) {
|
||||||
$query->without('gateway_tokens', 'documents', 'contacts.company', 'contacts'); // Exclude 'grandchildren' relation of 'client'
|
$query->without('gateway_tokens', 'documents', 'contacts.company', 'contacts'); // Exclude 'grandchildren' relation of 'client'
|
||||||
}])->find($this->contact_id);
|
}])->find($this->contact_id);
|
||||||
|
|
||||||
$this->company_gateway = CompanyGateway::withTrashed()->with('company')->find($this->company_gateway_id);
|
$this->company_gateway = CompanyGateway::withTrashed()->with('company')->find($this->company_gateway_id);
|
||||||
|
|
||||||
$company = $this->company_gateway->company;
|
$company = $this->company_gateway->company;
|
||||||
|
|
||||||
$this->client_name = $contact->client->name;
|
$this->client_name = $contact->client->name;
|
||||||
@ -240,6 +241,13 @@ class RequiredClientInfo extends Component
|
|||||||
$this->checkFields();
|
$this->checkFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (count($this->fields) === 0) {
|
||||||
|
$this->dispatch(
|
||||||
|
'passed-required-fields-check',
|
||||||
|
client_postal_code: $contact->client->postal_code
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if($this->unfilled_fields > 0 || ($this->company_gateway->always_show_required_fields || $this->is_subscription)) {
|
if($this->unfilled_fields > 0 || ($this->company_gateway->always_show_required_fields || $this->is_subscription)) {
|
||||||
$this->show_form = true;
|
$this->show_form = true;
|
||||||
}
|
}
|
||||||
@ -385,7 +393,6 @@ class RequiredClientInfo extends Component
|
|||||||
|
|
||||||
public function checkFields()
|
public function checkFields()
|
||||||
{
|
{
|
||||||
|
|
||||||
MultiDB::setDb($this->db);
|
MultiDB::setDb($this->db);
|
||||||
$_contact = ClientContact::withTrashed()->find($this->contact_id);
|
$_contact = ClientContact::withTrashed()->find($this->contact_id);
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
|||||||
* @property int $user_id
|
* @property int $user_id
|
||||||
* @property int|null $assigned_user_id
|
* @property int|null $assigned_user_id
|
||||||
* @property int $company_id
|
* @property int $company_id
|
||||||
|
* @property int $remaining_cycles
|
||||||
* @property string|null $product_ids
|
* @property string|null $product_ids
|
||||||
* @property int|null $frequency_id
|
* @property int|null $frequency_id
|
||||||
* @property string|null $auto_bill
|
* @property string|null $auto_bill
|
||||||
@ -117,6 +118,7 @@ class Subscription extends BaseModel
|
|||||||
'optional_recurring_product_ids',
|
'optional_recurring_product_ids',
|
||||||
'use_inventory_management',
|
'use_inventory_management',
|
||||||
'steps',
|
'steps',
|
||||||
|
'remaining_cycles',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
|
@ -39,9 +39,9 @@ class CreditCard implements LivewireMethodInterface
|
|||||||
public function authorizeView(array $data)
|
public function authorizeView(array $data)
|
||||||
{
|
{
|
||||||
$data['payment_method_id'] = GatewayType::CREDIT_CARD;
|
$data['payment_method_id'] = GatewayType::CREDIT_CARD;
|
||||||
|
$data['threeds'] = $this->powerboard->company_gateway->getConfigField('threeds');
|
||||||
|
|
||||||
$view = $this->powerboard->company_gateway->getConfigField('threeds') ? 'gateways.powerboard.credit_card.authorize' : 'gateways.powerboard.credit_card.authorize_no_3ds';
|
return render('gateways.powerboard.credit_card.authorize', $this->paymentData($data));
|
||||||
return render($view, $this->paymentData($data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function authorizeResponse($request)
|
public function authorizeResponse($request)
|
||||||
@ -76,7 +76,11 @@ class CreditCard implements LivewireMethodInterface
|
|||||||
$r = $this->powerboard->gatewayRequest('/v1/charges/3ds', (\App\Enum\HttpVerb::POST)->value, $payload, []);
|
$r = $this->powerboard->gatewayRequest('/v1/charges/3ds', (\App\Enum\HttpVerb::POST)->value, $payload, []);
|
||||||
|
|
||||||
if ($r->failed()) {
|
if ($r->failed()) {
|
||||||
return $this->processUnsuccessfulPayment($r);
|
|
||||||
|
$error_payload = $this->getErrorFromResponse($r);
|
||||||
|
return response()->json(['message' => $error_payload[0]], 400);
|
||||||
|
|
||||||
|
// return $this->processUnsuccessfulPayment($r);
|
||||||
}
|
}
|
||||||
|
|
||||||
$charge = $r->json();
|
$charge = $r->json();
|
||||||
@ -93,7 +97,7 @@ class CreditCard implements LivewireMethodInterface
|
|||||||
|
|
||||||
$payload = [
|
$payload = [
|
||||||
'_3ds' => [
|
'_3ds' => [
|
||||||
'id' => $charge_request['charge_3ds_id'],
|
'id' => array_key_exists('charge_3ds_id', $charge_request) ? $charge_request['charge_3ds_id'] : $charge_request['_3ds']['id'],
|
||||||
],
|
],
|
||||||
"capture" => false,
|
"capture" => false,
|
||||||
"authorization" => true,
|
"authorization" => true,
|
||||||
@ -215,6 +219,8 @@ class CreditCard implements LivewireMethodInterface
|
|||||||
|
|
||||||
public function paymentData(array $data): array
|
public function paymentData(array $data): array
|
||||||
{
|
{
|
||||||
|
$this->powerboard->init();
|
||||||
|
|
||||||
if($this->cba_gateway->verification_status != "completed")
|
if($this->cba_gateway->verification_status != "completed")
|
||||||
throw new PaymentFailed("This payment method is not configured as yet. Reference Powerboard portal for further information", 400);
|
throw new PaymentFailed("This payment method is not configured as yet. Reference Powerboard portal for further information", 400);
|
||||||
|
|
||||||
@ -260,11 +266,8 @@ class CreditCard implements LivewireMethodInterface
|
|||||||
nlog($r->body());
|
nlog($r->body());
|
||||||
|
|
||||||
if($r->failed()){
|
if($r->failed()){
|
||||||
|
|
||||||
$error_payload = $this->getErrorFromResponse($r);
|
$error_payload = $this->getErrorFromResponse($r);
|
||||||
|
|
||||||
throw new PaymentFailed($error_payload[0], $error_payload[1]);
|
throw new PaymentFailed($error_payload[0], $error_payload[1]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$charge = (new \App\PaymentDrivers\CBAPowerBoard\Models\Parse())->encode(Charge::class, $r->object()->resource->data) ?? $r->throw();
|
$charge = (new \App\PaymentDrivers\CBAPowerBoard\Models\Parse())->encode(Charge::class, $r->object()->resource->data) ?? $r->throw();
|
||||||
@ -303,7 +306,8 @@ class CreditCard implements LivewireMethodInterface
|
|||||||
$r = $this->powerboard->gatewayRequest('/v1/charges/3ds', (\App\Enum\HttpVerb::POST)->value, $payload, []);
|
$r = $this->powerboard->gatewayRequest('/v1/charges/3ds', (\App\Enum\HttpVerb::POST)->value, $payload, []);
|
||||||
|
|
||||||
if ($r->failed()) {
|
if ($r->failed()) {
|
||||||
return $this->processUnsuccessfulPayment($r);
|
$error_payload = $this->getErrorFromResponse($r);
|
||||||
|
return response()->json(['message' => $error_payload[0]], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
$charge = $r->json();
|
$charge = $r->json();
|
||||||
@ -351,7 +355,7 @@ class CreditCard implements LivewireMethodInterface
|
|||||||
|
|
||||||
$payload = [
|
$payload = [
|
||||||
'_3ds' => [
|
'_3ds' => [
|
||||||
'id' => $charge_request['charge_3ds_id'],
|
'id' => array_key_exists('charge_3ds_id', $charge_request) ? $charge_request['charge_3ds_id'] : $charge_request['_3ds']['id'],
|
||||||
],
|
],
|
||||||
"amount"=> $this->powerboard->payment_hash->data->amount_with_fee, //@phpstan-ignore-line
|
"amount"=> $this->powerboard->payment_hash->data->amount_with_fee, //@phpstan-ignore-line
|
||||||
"currency"=> $this->powerboard->client->currency()->code,
|
"currency"=> $this->powerboard->client->currency()->code,
|
||||||
@ -394,6 +398,9 @@ class CreditCard implements LivewireMethodInterface
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
session()->flash('message', ctrans('texts.payment_token_not_found'));
|
||||||
|
|
||||||
|
return redirect()->back();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processSuccessfulPayment(Charge $charge)
|
public function processSuccessfulPayment(Charge $charge)
|
||||||
@ -442,6 +449,7 @@ class CreditCard implements LivewireMethodInterface
|
|||||||
$error_message = "Unknown error";
|
$error_message = "Unknown error";
|
||||||
|
|
||||||
match($error_object->error->code) {
|
match($error_object->error->code) {
|
||||||
|
"UnfulfilledCondition" => $error_message = $error_object->error->details->messages[0] ?? $error_object->error->message ?? "Unknown error",
|
||||||
"GatewayError" => $error_message = $error_object->error->message,
|
"GatewayError" => $error_message = $error_object->error->message,
|
||||||
"UnfulfilledCondition" => $error_message = $error_object->error->message,
|
"UnfulfilledCondition" => $error_message = $error_object->error->message,
|
||||||
"transaction_declined" => $error_message = $error_object->error->details[0]->status_code_description,
|
"transaction_declined" => $error_message = $error_object->error->details[0]->status_code_description,
|
||||||
@ -455,11 +463,29 @@ class CreditCard implements LivewireMethodInterface
|
|||||||
}
|
}
|
||||||
public function processUnsuccessfulPayment($response)
|
public function processUnsuccessfulPayment($response)
|
||||||
{
|
{
|
||||||
|
$error = $this->getErrorFromResponse($response);
|
||||||
|
|
||||||
$error_payload = $this->getErrorFromResponse($response);
|
$this->powerboard->sendFailureMail($error[0]);
|
||||||
|
|
||||||
return response()->json(['message' => $error_payload[0], 'code' => $error_payload[1]], $error_payload[1]);
|
// $message = [
|
||||||
|
// 'server_response' => $server_response,
|
||||||
|
// 'data' => $this->stripe->payment_hash->data,
|
||||||
|
// ];
|
||||||
|
|
||||||
|
SystemLogger::dispatch(
|
||||||
|
$error[0],
|
||||||
|
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||||
|
SystemLog::EVENT_GATEWAY_FAILURE,
|
||||||
|
SystemLog::TYPE_POWERBOARD,
|
||||||
|
$this->powerboard->client,
|
||||||
|
$this->powerboard->client->company,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (request()->wantsJson()) {
|
||||||
|
return response()->json($error[0], 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new PaymentFailed('Failed to process the payment.', $error[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,16 @@ class CBAPowerBoardPaymentDriver extends BaseDriver
|
|||||||
|
|
||||||
public function getClientRequiredFields(): array
|
public function getClientRequiredFields(): array
|
||||||
{
|
{
|
||||||
return [];
|
$fields = [];
|
||||||
|
|
||||||
|
if ($this->company_gateway->require_client_name) {
|
||||||
|
$fields[] = ['name' => 'client_name', 'label' => ctrans('texts.client_name'), 'type' => 'text', 'validation' => 'required'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$fields[] = ['name' => 'contact_first_name', 'label' => ctrans('texts.first_name'), 'type' => 'text', 'validation' => 'required'];
|
||||||
|
$fields[] = ['name' => 'contact_last_name', 'label' => ctrans('texts.last_name'), 'type' => 'text', 'validation' => 'required'];
|
||||||
|
|
||||||
|
return $fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash)
|
public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash)
|
||||||
|
@ -1055,8 +1055,8 @@ class SubscriptionService
|
|||||||
$recurring_invoice->line_items = $subscription_repo->generateLineItems($this->subscription, true, false);
|
$recurring_invoice->line_items = $subscription_repo->generateLineItems($this->subscription, true, false);
|
||||||
$recurring_invoice->subscription_id = $this->subscription->id;
|
$recurring_invoice->subscription_id = $this->subscription->id;
|
||||||
$recurring_invoice->frequency_id = $this->subscription->frequency_id ?: RecurringInvoice::FREQUENCY_MONTHLY;
|
$recurring_invoice->frequency_id = $this->subscription->frequency_id ?: RecurringInvoice::FREQUENCY_MONTHLY;
|
||||||
|
$recurring_invoice->remaining_cycles = $this->subscription->remaining_cycles ?? -1;
|
||||||
$recurring_invoice->date = now();
|
$recurring_invoice->date = now();
|
||||||
$recurring_invoice->remaining_cycles = -1;
|
|
||||||
$recurring_invoice->auto_bill = $client->getSetting('auto_bill');
|
$recurring_invoice->auto_bill = $client->getSetting('auto_bill');
|
||||||
$recurring_invoice->auto_bill_enabled = $this->setAutoBillFlag($recurring_invoice->auto_bill);
|
$recurring_invoice->auto_bill_enabled = $this->setAutoBillFlag($recurring_invoice->auto_bill);
|
||||||
$recurring_invoice->due_date_days = 'terms';
|
$recurring_invoice->due_date_days = 'terms';
|
||||||
@ -1089,7 +1089,7 @@ class SubscriptionService
|
|||||||
$recurring_invoice->subscription_id = $this->subscription->id;
|
$recurring_invoice->subscription_id = $this->subscription->id;
|
||||||
$recurring_invoice->frequency_id = $this->subscription->frequency_id ?: RecurringInvoice::FREQUENCY_MONTHLY;
|
$recurring_invoice->frequency_id = $this->subscription->frequency_id ?: RecurringInvoice::FREQUENCY_MONTHLY;
|
||||||
$recurring_invoice->date = now()->addSeconds($client->timezone_offset());
|
$recurring_invoice->date = now()->addSeconds($client->timezone_offset());
|
||||||
$recurring_invoice->remaining_cycles = -1;
|
$recurring_invoice->remaining_cycles = $this->subscription->remaining_cycles ?? -1;
|
||||||
$recurring_invoice->auto_bill = $client->getSetting('auto_bill');
|
$recurring_invoice->auto_bill = $client->getSetting('auto_bill');
|
||||||
$recurring_invoice->auto_bill_enabled = $this->setAutoBillFlag($recurring_invoice->auto_bill);
|
$recurring_invoice->auto_bill_enabled = $this->setAutoBillFlag($recurring_invoice->auto_bill);
|
||||||
$recurring_invoice->due_date_days = 'terms';
|
$recurring_invoice->due_date_days = 'terms';
|
||||||
|
@ -73,6 +73,7 @@ class SubscriptionTransformer extends EntityTransformer
|
|||||||
'optional_product_ids' => (string) $subscription->optional_product_ids,
|
'optional_product_ids' => (string) $subscription->optional_product_ids,
|
||||||
'registration_required' => (bool) $subscription->registration_required,
|
'registration_required' => (bool) $subscription->registration_required,
|
||||||
'steps' => $subscription->steps,
|
'steps' => $subscription->steps,
|
||||||
|
'remaining_cycles' => (int) $subscription->remaining_cycles,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3891,7 +3891,7 @@ $lang = array(
|
|||||||
'payment_method_saving_failed' => 'Payment method can\'t be saved for future use.',
|
'payment_method_saving_failed' => 'Payment method can\'t be saved for future use.',
|
||||||
'pay_with' => 'Pay with',
|
'pay_with' => 'Pay with',
|
||||||
'n/a' => 'N/A',
|
'n/a' => 'N/A',
|
||||||
'by_clicking_next_you_accept_terms' => 'By clicking "Next step" you accept terms.',
|
'by_clicking_next_you_accept_terms' => 'By clicking "Next" you accept terms.',
|
||||||
'not_specified' => 'Not specified',
|
'not_specified' => 'Not specified',
|
||||||
'before_proceeding_with_payment_warning' => 'Before proceeding with payment, you have to fill following fields',
|
'before_proceeding_with_payment_warning' => 'Before proceeding with payment, you have to fill following fields',
|
||||||
'after_completing_go_back_to_previous_page' => 'After completing, go back to previous page.',
|
'after_completing_go_back_to_previous_page' => 'After completing, go back to previous page.',
|
||||||
|
1
public/build/assets/app-106dcc58.css
vendored
Normal file
1
public/build/assets/app-106dcc58.css
vendored
Normal file
File diff suppressed because one or more lines are too long
13
public/build/assets/authorize-powerboard-card-9db77713.js
vendored
Normal file
13
public/build/assets/authorize-powerboard-card-9db77713.js
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import{i as a,w as d}from"./wait-8f4ae121.js";/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/async function i(){const t={name:navigator.userAgent.substring(0,100),java_enabled:navigator.javaEnabled()?"true":"false",language:navigator.language||navigator.userLanguage,screen_height:window.screen.height.toString(),screen_width:window.screen.width.toString(),time_zone:(new Date().getTimezoneOffset()*-1).toString(),color_depth:window.screen.colorDepth.toString()};document.querySelector('input[name="browser_details"]').value=JSON.stringify(t);const n=JSON.stringify({...Object.fromEntries(new FormData(document.getElementById("server-response"))),gateway_response:Array.from(document.querySelectorAll("input[name=gateway_response]")).find(e=>e.value).value}),o=document.querySelector("meta[name=store_route]");try{const e=await fetch(o.content,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"XMLHttpRequest",Accept:"application/json","X-CSRF-Token":document.querySelector('meta[name="csrf-token"]').content},body:n});return e.ok?await e.json():await e.json().then(r=>{throw new Error(r.message??"Unknown error.")})}catch(e){document.getElementById("errors").textContent=`Sorry, your transaction could not be processed...
|
||||||
|
|
||||||
|
${e.message}`,document.getElementById("errors").hidden=!1;let r=document.getElementById("authorize-card");throw r.disabled=!1,r.querySelector("svg").classList.add("hidden"),r.querySelector("span").classList.remove("hidden"),console.error("Fetch error:",e),e}}async function c(){try{const t=await i();if(t.status==="not_authenticated"||t==="not_authenticated")throw s(),new Error("There was an issue authenticating this payment method.");if(t.status==="authentication_not_supported")return document.querySelector('input[name="browser_details"]').value=null,document.querySelector('input[name="charge"]').value=JSON.stringify(t),document.getElementById("server-response").submit();const n=new cba.Canvas3ds("#widget-3dsecure",t._3ds.token);n.load(),document.getElementById("widget").classList.add("hidden"),n.on("chargeAuthSuccess",function(e){document.querySelector('input[name="browser_details"]').value=null,document.querySelector('input[name="charge"]').value=JSON.stringify(e),document.getElementById("server-response").submit()}),n.on("chargeAuthReject",function(e){document.getElementById("errors").textContent="Sorry, your transaction could not be processed...",document.getElementById("errors").hidden=!1,s()}),n.load()}catch(t){console.error("Error fetching 3DS Token:",t),document.getElementById("errors").textContent=`Sorry, your transaction could not be processed...
|
||||||
|
|
||||||
|
${t}`,document.getElementById("errors").hidden=!1;let n=document.getElementById("authorize-card");n.disabled=!1,n.querySelector("svg").classList.add("hidden"),n.querySelector("span").classList.remove("hidden")}}function u(){l();const t=document.querySelector("meta[name=public_key]"),n=document.querySelector("meta[name=gateway_id]"),o=document.querySelector("meta[name=environment]"),e=new cba.HtmlWidget("#widget",t==null?void 0:t.content,n==null?void 0:n.content);e.setEnv(o==null?void 0:o.content),e.useAutoResize(),e.interceptSubmitForm("#stepone"),e.onFinishInsert('#server-response input[name="gateway_response"]',"payment_source"),e.setFormFields(["card_name*"]),e.load();let r=document.getElementById("authorize-card");return r.disabled=!1,r.querySelector("svg").classList.add("hidden"),r.querySelector("span").classList.remove("hidden"),e}function l(){var t;document.querySelector("#widget").innerHTML="",(t=document.querySelector("#widget"))==null||t.classList.remove("hidden"),document.querySelector("#widget-3dsecure").innerHTML=""}function s(){const t=u();function n(){let r=document.getElementById("pay-now");r.disabled=t.isInvalidForm()}t.trigger("tab",n),t.trigger("submit_form",n),t.trigger("tab",n),t.on("finish",function(r){document.getElementById("errors").hidden=!0,c()});const o=document.querySelector('input[name="payment-type"]');o&&o.click();let e=document.getElementById("authorize-card");e.addEventListener("click",()=>{const r=document.getElementById("widget");if(t.getValidationState(),!t.isValidForm()&&r.offsetParent!==null){e.disabled=!1,e.querySelector("svg").classList.add("hidden"),e.querySelector("span").classList.remove("hidden");return}e.disabled=!0,e.querySelector("svg").classList.remove("hidden"),e.querySelector("span").classList.add("hidden"),r.offsetParent!==null?document.getElementById("stepone_submit").click():document.getElementById("server-response").submit()})}a()?s():d("#").then(s);
|
13
public/build/assets/powerboard-credit-card-127361fb.js
vendored
Normal file
13
public/build/assets/powerboard-credit-card-127361fb.js
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import{i as s,w as c}from"./wait-8f4ae121.js";/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/function i(){const t=document.querySelector("meta[name=public_key]"),n=document.querySelector("meta[name=gateway_id]"),o=document.querySelector("meta[name=environment]"),e=new cba.HtmlWidget("#widget",t==null?void 0:t.content,n==null?void 0:n.content);e.setEnv(o==null?void 0:o.content),e.useAutoResize(),e.interceptSubmitForm("#stepone"),e.onFinishInsert('#server-response input[name="gateway_response"]',"payment_source"),e.setFormFields(["card_name*"]),e.reload();let r=document.getElementById("pay-now");return r.disabled=!1,r.querySelector("svg").classList.add("hidden"),r.querySelector("span").classList.remove("hidden"),document.querySelector('#server-response input[name="gateway_response"]').value="",e}function u(){var t,n,o;(t=document.querySelector("#widget"))==null||t.replaceChildren(),(n=document.querySelector("#widget"))==null||n.classList.remove("hidden"),(o=document.querySelector("#widget-3dsecure"))==null||o.replaceChildren()}function d(){u();const t=i();t.on("finish",()=>{document.getElementById("errors").hidden=!0,l()}),t.on("submit",function(e){document.getElementById("errors").hidden=!0});let n=document.getElementById("pay-now");n.addEventListener("click",()=>{const e=document.getElementById("widget");if(t.getValidationState(),!t.isValidForm()&&e.offsetParent!==null){n.disabled=!1,n.querySelector("svg").classList.add("hidden"),n.querySelector("span").classList.remove("hidden");return}n.disabled=!0,n.querySelector("svg").classList.remove("hidden"),n.querySelector("span").classList.add("hidden");let r=document.querySelector("input[name=token-billing-checkbox]:checked");r&&(document.getElementById("store_card").value=r.value),e.offsetParent!==null?document.getElementById("stepone_submit").click():document.getElementById("server-response").submit()}),document.getElementById("toggle-payment-with-credit-card").addEventListener("click",e=>{var a;document.getElementById("widget").classList.remove("hidden"),document.getElementById("save-card--container").style.display="grid",document.querySelector("input[name=token]").value="",(a=document.querySelector("#powerboard-payment-container"))==null||a.classList.remove("hidden")}),Array.from(document.getElementsByClassName("toggle-payment-with-token")).forEach(e=>e.addEventListener("click",r=>{var a;document.getElementById("widget").classList.add("hidden"),document.getElementById("save-card--container").style.display="none",document.querySelector("input[name=token]").value=r.target.dataset.token,(a=document.querySelector("#powerboard-payment-container"))==null||a.classList.add("hidden")}));const o=document.querySelector('input[name="payment-type"]');o&&o.click()}async function l(){try{const t=await m();if(t.status==="not_authenticated"||t==="not_authenticated")throw d(),new Error("There was an issue authenticating this payment method.");if(t.status==="authentication_not_supported"){document.querySelector('input[name="browser_details"]').value=null,document.querySelector('input[name="charge"]').value=JSON.stringify(t);let e=document.querySelector("input[name=token-billing-checkbox]:checked");return e&&(document.getElementById("store_card").value=e.value),document.getElementById("server-response").submit()}const n=new cba.Canvas3ds("#widget-3dsecure",t._3ds.token);n.load(),document.getElementById("widget").classList.add("hidden"),n.on("chargeAuthSuccess",function(e){document.querySelector('input[name="browser_details"]').value=null,document.querySelector('input[name="charge"]').value=JSON.stringify(e);let r=document.querySelector("input[name=token-billing-checkbox]:checked");r&&(document.getElementById("store_card").value=r.value),document.getElementById("server-response").submit()}),n.on("chargeAuthReject",function(e){document.getElementById("errors").textContent="Sorry, your transaction could not be processed...",document.getElementById("errors").hidden=!1,d()}),n.load()}catch(t){document.getElementById("errors").textContent=`Sorry, your transaction could not be processed...
|
||||||
|
|
||||||
|
${t}`,document.getElementById("errors").hidden=!1}}async function m(){const t={name:navigator.userAgent.substring(0,100),java_enabled:navigator.javaEnabled()?"true":"false",language:navigator.language||navigator.userLanguage,screen_height:window.screen.height.toString(),screen_width:window.screen.width.toString(),time_zone:(new Date().getTimezoneOffset()*-1).toString(),color_depth:window.screen.colorDepth.toString()};document.querySelector('input[name="browser_details"]').value=JSON.stringify(t);const n=JSON.stringify(Object.fromEntries(new FormData(document.getElementById("server-response")))),o=document.querySelector("meta[name=payments_route]");try{const e=await fetch(o.content,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"XMLHttpRequest",Accept:"application/json","X-CSRF-Token":document.querySelector('meta[name="csrf-token"]').content},body:n});return e.ok?await e.json():await e.json().then(r=>{throw new Error(r.message??"Unknown error.")})}catch(e){throw document.getElementById("errors").textContent=`Sorry, your transaction could not be processed...
|
||||||
|
|
||||||
|
${e.message}`,document.getElementById("errors").hidden=!1,console.error("Fetch error:",e),e}}s()?d():c("#powerboard-credit-card-payment").then(()=>d());
|
13
public/build/assets/powerboard-credit-card-f720a335.js
vendored
Normal file
13
public/build/assets/powerboard-credit-card-f720a335.js
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import{i as s,w as c}from"./wait-8f4ae121.js";/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/function i(){const t=document.querySelector("meta[name=public_key]"),n=document.querySelector("meta[name=gateway_id]"),o=document.querySelector("meta[name=environment]"),e=new cba.HtmlWidget("#widget",t==null?void 0:t.content,n==null?void 0:n.content);e.setEnv(o==null?void 0:o.content),e.useAutoResize(),e.interceptSubmitForm("#stepone"),e.onFinishInsert('#server-response input[name="gateway_response"]',"payment_source"),e.setFormFields(["card_name*"]),e.reload();let r=document.getElementById("pay-now");return r.disabled=!1,r.querySelector("svg").classList.add("hidden"),r.querySelector("span").classList.remove("hidden"),document.querySelector('#server-response input[name="gateway_response"]').value="",e}function u(){var t,n,o;(t=document.querySelector("#widget"))==null||t.replaceChildren(),(n=document.querySelector("#widget"))==null||n.classList.remove("hidden"),(o=document.querySelector("#widget-3dsecure"))==null||o.replaceChildren()}function a(){u();const t=i();t.on("finish",()=>{document.getElementById("errors").hidden=!0,l()}),t.on("submit",function(e){document.getElementById("errors").hidden=!0});let n=document.getElementById("pay-now");n.addEventListener("click",()=>{const e=document.getElementById("widget");if(t.getValidationState(),!t.isValidForm()&&e.offsetParent!==null){n.disabled=!1,n.querySelector("svg").classList.add("hidden"),n.querySelector("span").classList.remove("hidden");return}n.disabled=!0,n.querySelector("svg").classList.remove("hidden"),n.querySelector("span").classList.add("hidden");let r=document.querySelector("input[name=token-billing-checkbox]:checked");r&&(document.getElementById("store_card").value=r.value),e.offsetParent!==null?document.getElementById("stepone_submit").click():document.getElementById("server-response").submit()}),document.getElementById("toggle-payment-with-credit-card").addEventListener("click",e=>{var d;document.getElementById("widget").classList.remove("hidden"),document.getElementById("save-card--container").style.display="grid",document.querySelector("input[name=token]").value="",(d=document.querySelector("#powerboard-payment-container"))==null||d.classList.remove("hidden")}),Array.from(document.getElementsByClassName("toggle-payment-with-token")).forEach(e=>e.addEventListener("click",r=>{var d;document.getElementById("widget").classList.add("hidden"),document.getElementById("save-card--container").style.display="none",document.querySelector("input[name=token]").value=r.target.dataset.token,(d=document.querySelector("#powerboard-payment-container"))==null||d.classList.add("hidden")}));const o=document.querySelector('input[name="payment-type"]');o&&o.click()}async function l(){try{const t=await m();if(t.status==="not_authenticated"||t==="not_authenticated")throw a(),new Error("There was an issue authenticating this payment method.");if(t.status==="authentication_not_supported"){document.querySelector('input[name="browser_details"]').value=null,document.querySelector('input[name="charge"]').value=JSON.stringify(t);let e=document.querySelector("input[name=token-billing-checkbox]:checked");return e&&(document.getElementById("store_card").value=e.value),document.getElementById("server-response").submit()}const n=new cba.Canvas3ds("#widget-3dsecure",t._3ds.token);n.load(),document.getElementById("widget").classList.add("hidden"),n.on("chargeAuthSuccess",function(e){document.querySelector('input[name="browser_details"]').value=null,document.querySelector('input[name="charge"]').value=JSON.stringify(e);let r=document.querySelector("input[name=token-billing-checkbox]:checked");r&&(document.getElementById("store_card").value=r.value),document.getElementById("server-response").submit()}),n.on("chargeAuthReject",function(e){document.getElementById("errors").textContent="Sorry, your transaction could not be processed...",document.getElementById("errors").hidden=!1,a()}),n.load()}catch(t){console.error("Error fetching 3DS Token:",t),document.getElementById("errors").textContent=`Sorry, your transaction could not be processed...
|
||||||
|
|
||||||
|
${t}`,document.getElementById("errors").hidden=!1,a()}}async function m(){const t={name:navigator.userAgent.substring(0,100),java_enabled:navigator.javaEnabled()?"true":"false",language:navigator.language||navigator.userLanguage,screen_height:window.screen.height.toString(),screen_width:window.screen.width.toString(),time_zone:(new Date().getTimezoneOffset()*-1).toString(),color_depth:window.screen.colorDepth.toString()};document.querySelector('input[name="browser_details"]').value=JSON.stringify(t);const n=JSON.stringify(Object.fromEntries(new FormData(document.getElementById("server-response")))),o=document.querySelector("meta[name=payments_route]");try{const e=await fetch(o.content,{method:"POST",headers:{"Content-Type":"application/json","X-Requested-With":"XMLHttpRequest",Accept:"application/json","X-CSRF-Token":document.querySelector('meta[name="csrf-token"]').content},body:n});return e.ok?await e.json():await e.json().then(r=>{throw new Error(r.message??"Unknown error.")})}catch(e){document.getElementById("errors").textContent=`Sorry, your transaction could not be processed...
|
||||||
|
|
||||||
|
${e.message}`,document.getElementById("errors").hidden=!1,console.error("Fetch error:",e),a()}}s()?a():c("#powerboard-credit-card-payment").then(()=>a());
|
@ -48,6 +48,14 @@
|
|||||||
"isEntry": true,
|
"isEntry": true,
|
||||||
"src": "resources/js/clients/payment_methods/authorize-checkout-card.js"
|
"src": "resources/js/clients/payment_methods/authorize-checkout-card.js"
|
||||||
},
|
},
|
||||||
|
"resources/js/clients/payment_methods/authorize-powerboard-card.js": {
|
||||||
|
"file": "assets/authorize-powerboard-card-9db77713.js",
|
||||||
|
"imports": [
|
||||||
|
"_wait-8f4ae121.js"
|
||||||
|
],
|
||||||
|
"isEntry": true,
|
||||||
|
"src": "resources/js/clients/payment_methods/authorize-powerboard-card.js"
|
||||||
|
},
|
||||||
"resources/js/clients/payment_methods/authorize-stripe-acss.js": {
|
"resources/js/clients/payment_methods/authorize-stripe-acss.js": {
|
||||||
"file": "assets/authorize-stripe-acss-f6bd46c1.js",
|
"file": "assets/authorize-stripe-acss-f6bd46c1.js",
|
||||||
"imports": [
|
"imports": [
|
||||||
@ -141,6 +149,14 @@
|
|||||||
"isEntry": true,
|
"isEntry": true,
|
||||||
"src": "resources/js/clients/payments/paytrace-credit-card.js"
|
"src": "resources/js/clients/payments/paytrace-credit-card.js"
|
||||||
},
|
},
|
||||||
|
"resources/js/clients/payments/powerboard-credit-card.
|
||||||
|
"file": "assets/powerboard-credit-card-127361fb.js",
|
||||||
|
"imports": [
|
||||||
|
"_wait-8f4ae121.js"
|
||||||
|
],
|
||||||
|
"isEntry": true,
|
||||||
|
"src": "resources/js/clients/payments/powerboard-credit-card.js"
|
||||||
|
},
|
||||||
"resources/js/clients/payments/razorpay-aio.js": {
|
"resources/js/clients/payments/razorpay-aio.js": {
|
||||||
"file": "assets/razorpay-aio-f8e8c7f0.js",
|
"file": "assets/razorpay-aio-f8e8c7f0.js",
|
||||||
"imports": [
|
"imports": [
|
||||||
|
239
resources/js/clients/payment_methods/authorize-powerboard-card.js
vendored
Normal file
239
resources/js/clients/payment_methods/authorize-powerboard-card.js
vendored
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { instant, wait } from '../wait';
|
||||||
|
|
||||||
|
async function get3dsToken() {
|
||||||
|
const browserDetails = {
|
||||||
|
name: navigator.userAgent.substring(0, 100), // The full user agent string, which contains the browser name and version
|
||||||
|
java_enabled: navigator.javaEnabled() ? 'true' : 'false', // Indicates if Java is enabled in the browser
|
||||||
|
language: navigator.language || navigator.userLanguage, // The browser language
|
||||||
|
screen_height: window.screen.height.toString(), // Screen height in pixels
|
||||||
|
screen_width: window.screen.width.toString(), // Screen width in pixels
|
||||||
|
time_zone: (new Date().getTimezoneOffset() * -1).toString(), // Timezone offset in minutes (negative for behind UTC)
|
||||||
|
color_depth: window.screen.colorDepth.toString(), // Color depth in bits per pixel
|
||||||
|
};
|
||||||
|
|
||||||
|
document.querySelector('input[name="browser_details"]').value =
|
||||||
|
JSON.stringify(browserDetails);
|
||||||
|
|
||||||
|
const formData = JSON.stringify({
|
||||||
|
...Object.fromEntries(
|
||||||
|
new FormData(document.getElementById('server-response'))
|
||||||
|
),
|
||||||
|
gateway_response: Array.from(document.querySelectorAll('input[name=gateway_response]')).find(input => input.value).value,
|
||||||
|
});
|
||||||
|
|
||||||
|
const paymentsRoute = document.querySelector('meta[name=store_route]');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Return the fetch promise to handle it externally
|
||||||
|
const response = await fetch(paymentsRoute.content, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-Requested-With': 'XMLHttpRequest',
|
||||||
|
Accept: 'application/json',
|
||||||
|
'X-CSRF-Token': document.querySelector(
|
||||||
|
'meta[name="csrf-token"]'
|
||||||
|
).content,
|
||||||
|
},
|
||||||
|
body: formData,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
return await response.json().then((errorData) => {
|
||||||
|
throw new Error(errorData.message ?? 'Unknown error.');
|
||||||
|
});
|
||||||
|
|
||||||
|
// const text = await response.text();
|
||||||
|
// throw new Error(`Network response was not ok: ${response.statusText}. Response text: ${text}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return await response.json();
|
||||||
|
} catch (error) {
|
||||||
|
document.getElementById(
|
||||||
|
'errors'
|
||||||
|
).textContent = `Sorry, your transaction could not be processed...\n\n${error.message}`;
|
||||||
|
document.getElementById('errors').hidden = false;
|
||||||
|
|
||||||
|
|
||||||
|
let payNow = document.getElementById('authorize-card');
|
||||||
|
|
||||||
|
payNow.disabled = false;
|
||||||
|
payNow.querySelector('svg').classList.add('hidden');
|
||||||
|
payNow.querySelector('span').classList.remove('hidden');
|
||||||
|
|
||||||
|
console.error('Fetch error:', error); // Log error for debugging
|
||||||
|
throw error; //
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function process3ds() {
|
||||||
|
try {
|
||||||
|
const resource = await get3dsToken();
|
||||||
|
|
||||||
|
if (resource.status === 'not_authenticated' || resource === 'not_authenticated') {
|
||||||
|
authorize();
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
'There was an issue authenticating this payment method.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resource.status === 'authentication_not_supported') {
|
||||||
|
document.querySelector('input[name="browser_details"]').value =
|
||||||
|
null;
|
||||||
|
|
||||||
|
document.querySelector('input[name="charge"]').value =
|
||||||
|
JSON.stringify(resource);
|
||||||
|
|
||||||
|
return document.getElementById('server-response').submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
const canvas = new cba.Canvas3ds(
|
||||||
|
'#widget-3dsecure',
|
||||||
|
resource._3ds.token
|
||||||
|
);
|
||||||
|
|
||||||
|
canvas.load();
|
||||||
|
|
||||||
|
let widget = document.getElementById('widget');
|
||||||
|
widget.classList.add('hidden');
|
||||||
|
|
||||||
|
canvas.on('chargeAuthSuccess', function (data) {
|
||||||
|
document.querySelector('input[name="browser_details"]').value =
|
||||||
|
null;
|
||||||
|
|
||||||
|
document.querySelector('input[name="charge"]').value =
|
||||||
|
JSON.stringify(data);
|
||||||
|
|
||||||
|
document.getElementById('server-response').submit();
|
||||||
|
});
|
||||||
|
|
||||||
|
canvas.on('chargeAuthReject', function (data) {
|
||||||
|
document.getElementById(
|
||||||
|
'errors'
|
||||||
|
).textContent = `Sorry, your transaction could not be processed...`;
|
||||||
|
document.getElementById('errors').hidden = false;
|
||||||
|
|
||||||
|
authorize();
|
||||||
|
});
|
||||||
|
|
||||||
|
canvas.load();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching 3DS Token:', error);
|
||||||
|
|
||||||
|
document.getElementById(
|
||||||
|
'errors'
|
||||||
|
).textContent = `Sorry, your transaction could not be processed...\n\n${error}`;
|
||||||
|
document.getElementById('errors').hidden = false;
|
||||||
|
|
||||||
|
let payNow = document.getElementById('authorize-card');
|
||||||
|
|
||||||
|
payNow.disabled = false;
|
||||||
|
payNow.querySelector('svg').classList.add('hidden');
|
||||||
|
payNow.querySelector('span').classList.remove('hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup() {
|
||||||
|
reload();
|
||||||
|
|
||||||
|
const publicKey = document.querySelector('meta[name=public_key]');
|
||||||
|
const gatewayId = document.querySelector('meta[name=gateway_id]');
|
||||||
|
const env = document.querySelector('meta[name=environment]');
|
||||||
|
|
||||||
|
const widget = new cba.HtmlWidget(
|
||||||
|
'#widget',
|
||||||
|
publicKey?.content,
|
||||||
|
gatewayId?.content
|
||||||
|
);
|
||||||
|
|
||||||
|
widget.setEnv(env?.content);
|
||||||
|
widget.useAutoResize();
|
||||||
|
widget.interceptSubmitForm('#stepone');
|
||||||
|
widget.onFinishInsert(
|
||||||
|
'#server-response input[name="gateway_response"]',
|
||||||
|
'payment_source'
|
||||||
|
);
|
||||||
|
|
||||||
|
widget.setFormFields(['card_name*']);
|
||||||
|
|
||||||
|
widget.load();
|
||||||
|
|
||||||
|
let payNow = document.getElementById('authorize-card');
|
||||||
|
|
||||||
|
payNow.disabled = false;
|
||||||
|
payNow.querySelector('svg').classList.add('hidden');
|
||||||
|
payNow.querySelector('span').classList.remove('hidden');
|
||||||
|
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
function reload() {
|
||||||
|
document.querySelector('#widget').innerHTML = '';
|
||||||
|
document.querySelector('#widget')?.classList.remove('hidden');
|
||||||
|
document.querySelector('#widget-3dsecure').innerHTML = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function authorize() {
|
||||||
|
const widget = setup();
|
||||||
|
|
||||||
|
function handleTrigger() {
|
||||||
|
let payNow = document.getElementById('pay-now');
|
||||||
|
|
||||||
|
payNow.disabled = widget.isInvalidForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
widget.trigger('tab', handleTrigger);
|
||||||
|
widget.trigger('submit_form', handleTrigger);
|
||||||
|
widget.trigger('tab', handleTrigger);
|
||||||
|
|
||||||
|
widget.on('finish', function (data) {
|
||||||
|
document.getElementById('errors').hidden = true;
|
||||||
|
|
||||||
|
process3ds();
|
||||||
|
});
|
||||||
|
|
||||||
|
const first = document.querySelector('input[name="payment-type"]');
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
first.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
let authorizeCard = document.getElementById('authorize-card');
|
||||||
|
|
||||||
|
authorizeCard.addEventListener('click', () => {
|
||||||
|
const div = document.getElementById('widget');
|
||||||
|
|
||||||
|
widget.getValidationState();
|
||||||
|
|
||||||
|
if (!widget.isValidForm() && div.offsetParent !== null) {
|
||||||
|
authorizeCard.disabled = false;
|
||||||
|
authorizeCard.querySelector('svg').classList.add('hidden');
|
||||||
|
authorizeCard.querySelector('span').classList.remove('hidden');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
authorizeCard.disabled = true;
|
||||||
|
authorizeCard.querySelector('svg').classList.remove('hidden');
|
||||||
|
authorizeCard.querySelector('span').classList.add('hidden');
|
||||||
|
|
||||||
|
if (div.offsetParent !== null) {
|
||||||
|
document.getElementById('stepone_submit').click();
|
||||||
|
} else {
|
||||||
|
document.getElementById('server-response').submit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
instant() ? authorize() : wait('#').then(authorize);
|
276
resources/js/clients/payments/powerboard-credit-card.js
vendored
Normal file
276
resources/js/clients/payments/powerboard-credit-card.js
vendored
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { instant, wait } from '../wait';
|
||||||
|
|
||||||
|
function setup() {
|
||||||
|
const publicKey = document.querySelector('meta[name=public_key]');
|
||||||
|
const gatewayId = document.querySelector('meta[name=gateway_id]');
|
||||||
|
const env = document.querySelector('meta[name=environment]');
|
||||||
|
|
||||||
|
const widget = new cba.HtmlWidget(
|
||||||
|
'#widget',
|
||||||
|
publicKey?.content,
|
||||||
|
gatewayId?.content
|
||||||
|
);
|
||||||
|
|
||||||
|
widget.setEnv(env?.content);
|
||||||
|
widget.useAutoResize();
|
||||||
|
widget.interceptSubmitForm('#stepone');
|
||||||
|
widget.onFinishInsert(
|
||||||
|
'#server-response input[name="gateway_response"]',
|
||||||
|
'payment_source'
|
||||||
|
);
|
||||||
|
|
||||||
|
widget.setFormFields(['card_name*']);
|
||||||
|
widget.reload();
|
||||||
|
|
||||||
|
let payNow = document.getElementById('pay-now');
|
||||||
|
|
||||||
|
payNow.disabled = false;
|
||||||
|
payNow.querySelector('svg').classList.add('hidden');
|
||||||
|
payNow.querySelector('span').classList.remove('hidden');
|
||||||
|
|
||||||
|
document.querySelector(
|
||||||
|
'#server-response input[name="gateway_response"]'
|
||||||
|
).value = '';
|
||||||
|
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
function reload() {
|
||||||
|
document.querySelector('#widget')?.replaceChildren();
|
||||||
|
document.querySelector('#widget')?.classList.remove('hidden');
|
||||||
|
|
||||||
|
document.querySelector('#widget-3dsecure')?.replaceChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
function pay() {
|
||||||
|
reload();
|
||||||
|
|
||||||
|
const widget = setup();
|
||||||
|
|
||||||
|
widget.on('finish', () => {
|
||||||
|
document.getElementById('errors').hidden = true;
|
||||||
|
|
||||||
|
process3ds();
|
||||||
|
});
|
||||||
|
|
||||||
|
widget.on('submit', function (data) {
|
||||||
|
document.getElementById('errors').hidden = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
let payNow = document.getElementById('pay-now');
|
||||||
|
|
||||||
|
payNow.addEventListener('click', () => {
|
||||||
|
const div = document.getElementById('widget');
|
||||||
|
|
||||||
|
widget.getValidationState();
|
||||||
|
|
||||||
|
if (!widget.isValidForm() && div.offsetParent !== null) {
|
||||||
|
payNow.disabled = false;
|
||||||
|
payNow.querySelector('svg').classList.add('hidden');
|
||||||
|
payNow.querySelector('span').classList.remove('hidden');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
payNow.disabled = true;
|
||||||
|
payNow.querySelector('svg').classList.remove('hidden');
|
||||||
|
payNow.querySelector('span').classList.add('hidden');
|
||||||
|
|
||||||
|
let storeCard = document.querySelector(
|
||||||
|
'input[name=token-billing-checkbox]:checked'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (storeCard) {
|
||||||
|
document.getElementById('store_card').value = storeCard.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (div.offsetParent !== null)
|
||||||
|
document.getElementById('stepone_submit').click();
|
||||||
|
else document.getElementById('server-response').submit();
|
||||||
|
});
|
||||||
|
|
||||||
|
document
|
||||||
|
.getElementById('toggle-payment-with-credit-card')
|
||||||
|
.addEventListener('click', (element) => {
|
||||||
|
let widget = document.getElementById('widget');
|
||||||
|
|
||||||
|
widget.classList.remove('hidden');
|
||||||
|
|
||||||
|
document.getElementById('save-card--container').style.display =
|
||||||
|
'grid';
|
||||||
|
document.querySelector('input[name=token]').value = '';
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelector('#powerboard-payment-container')
|
||||||
|
?.classList.remove('hidden');
|
||||||
|
});
|
||||||
|
|
||||||
|
Array.from(
|
||||||
|
document.getElementsByClassName('toggle-payment-with-token')
|
||||||
|
).forEach((element) =>
|
||||||
|
element.addEventListener('click', (element) => {
|
||||||
|
document.getElementById('widget').classList.add('hidden');
|
||||||
|
document.getElementById('save-card--container').style.display =
|
||||||
|
'none';
|
||||||
|
document.querySelector('input[name=token]').value =
|
||||||
|
element.target.dataset.token;
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelector('#powerboard-payment-container')
|
||||||
|
?.classList.add('hidden');
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const first = document.querySelector('input[name="payment-type"]');
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
first.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function process3ds() {
|
||||||
|
try {
|
||||||
|
const resource = await get3dsToken();
|
||||||
|
|
||||||
|
if (resource.status === 'not_authenticated' || resource === 'not_authenticated') {
|
||||||
|
pay();
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
'There was an issue authenticating this payment method.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resource.status === 'authentication_not_supported') {
|
||||||
|
document.querySelector('input[name="browser_details"]').value =
|
||||||
|
null;
|
||||||
|
|
||||||
|
document.querySelector('input[name="charge"]').value =
|
||||||
|
JSON.stringify(resource);
|
||||||
|
|
||||||
|
let storeCard = document.querySelector(
|
||||||
|
'input[name=token-billing-checkbox]:checked'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (storeCard) {
|
||||||
|
document.getElementById('store_card').value = storeCard.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return document.getElementById('server-response').submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
const canvas = new cba.Canvas3ds(
|
||||||
|
'#widget-3dsecure',
|
||||||
|
resource._3ds.token
|
||||||
|
);
|
||||||
|
canvas.load();
|
||||||
|
|
||||||
|
let widget = document.getElementById('widget');
|
||||||
|
widget.classList.add('hidden');
|
||||||
|
|
||||||
|
canvas.on('chargeAuthSuccess', function (data) {
|
||||||
|
document.querySelector('input[name="browser_details"]').value =
|
||||||
|
null;
|
||||||
|
|
||||||
|
document.querySelector('input[name="charge"]').value =
|
||||||
|
JSON.stringify(data);
|
||||||
|
|
||||||
|
let storeCard = document.querySelector(
|
||||||
|
'input[name=token-billing-checkbox]:checked'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (storeCard) {
|
||||||
|
document.getElementById('store_card').value = storeCard.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('server-response').submit();
|
||||||
|
});
|
||||||
|
|
||||||
|
canvas.on('chargeAuthReject', function (data) {
|
||||||
|
document.getElementById(
|
||||||
|
'errors'
|
||||||
|
).textContent = `Sorry, your transaction could not be processed...`;
|
||||||
|
document.getElementById('errors').hidden = false;
|
||||||
|
|
||||||
|
pay();
|
||||||
|
});
|
||||||
|
|
||||||
|
canvas.load();
|
||||||
|
} catch (error) {
|
||||||
|
document.getElementById(
|
||||||
|
'errors'
|
||||||
|
).textContent = `Sorry, your transaction could not be processed...\n\n${error}`;
|
||||||
|
document.getElementById('errors').hidden = false;
|
||||||
|
pay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function get3dsToken() {
|
||||||
|
const browserDetails = {
|
||||||
|
name: navigator.userAgent.substring(0, 100), // The full user agent string, which contains the browser name and version
|
||||||
|
java_enabled: navigator.javaEnabled() ? 'true' : 'false', // Indicates if Java is enabled in the browser
|
||||||
|
language: navigator.language || navigator.userLanguage, // The browser language
|
||||||
|
screen_height: window.screen.height.toString(), // Screen height in pixels
|
||||||
|
screen_width: window.screen.width.toString(), // Screen width in pixels
|
||||||
|
time_zone: (new Date().getTimezoneOffset() * -1).toString(), // Timezone offset in minutes (negative for behind UTC)
|
||||||
|
color_depth: window.screen.colorDepth.toString(), // Color depth in bits per pixel
|
||||||
|
};
|
||||||
|
|
||||||
|
document.querySelector('input[name="browser_details"]').value =
|
||||||
|
JSON.stringify(browserDetails);
|
||||||
|
|
||||||
|
const formData = JSON.stringify(
|
||||||
|
Object.fromEntries(
|
||||||
|
new FormData(document.getElementById('server-response'))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const paymentsRoute = document.querySelector('meta[name=payments_route]');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Return the fetch promise to handle it externally
|
||||||
|
const response = await fetch(paymentsRoute.content, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-Requested-With': 'XMLHttpRequest',
|
||||||
|
Accept: 'application/json',
|
||||||
|
'X-CSRF-Token': document.querySelector(
|
||||||
|
'meta[name="csrf-token"]'
|
||||||
|
).content,
|
||||||
|
},
|
||||||
|
body: formData,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
return await response.json().then((errorData) => {
|
||||||
|
throw new Error(errorData.message ?? 'Unknown error.');
|
||||||
|
});
|
||||||
|
|
||||||
|
// const text = await response.text();
|
||||||
|
// throw new Error(`Network response was not ok: ${response.statusText}. Response text: ${text}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return await response.json();
|
||||||
|
} catch (error) {
|
||||||
|
document.getElementById(
|
||||||
|
'errors'
|
||||||
|
).textContent = `Sorry, your transaction could not be processed...\n\n${error.message}`;
|
||||||
|
document.getElementById('errors').hidden = false;
|
||||||
|
|
||||||
|
console.error('Fetch error:', error); // Log error for debugging
|
||||||
|
pay();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
instant() ? pay() : wait('#powerboard-credit-card-payment').then(() => pay());
|
@ -304,6 +304,14 @@
|
|||||||
<span>{{ $total }}</span>
|
<span>{{ $total }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@if(isset($tax))
|
||||||
|
<div class="flex font-semibold justify-between py-1 text-sm uppercase border-t-2">
|
||||||
|
<span>{{ ctrans('texts.tax') }}</span>
|
||||||
|
<span>{{ $tax }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@endif
|
||||||
|
|
||||||
<div class="mx-auto text-center mt-20 content-center" x-data="{open: @entangle('payment_started').live, toggle: @entangle('payment_confirmed').live, buttonDisabled: false}" x-show.important="open" x-transition>
|
<div class="mx-auto text-center mt-20 content-center" x-data="{open: @entangle('payment_started').live, toggle: @entangle('payment_confirmed').live, buttonDisabled: false}" x-show.important="open" x-transition>
|
||||||
<h2 class="text-2xl font-bold tracking-wide border-b-2 pb-4">{{ $heading_text ?? ctrans('texts.checkout') }}</h2>
|
<h2 class="text-2xl font-bold tracking-wide border-b-2 pb-4">{{ $heading_text ?? ctrans('texts.checkout') }}</h2>
|
||||||
@if (session()->has('message'))
|
@if (session()->has('message'))
|
||||||
|
@ -13,8 +13,11 @@
|
|||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-end items-center px-4 py-4">
|
<div class="flex flex-col items-end px-4 py-4">
|
||||||
<button id="accept-terms-button" class="button button-primary bg-primary hover:bg-primary-darken float-end">{{ ctrans('texts.next') }}</button>
|
<div class="w-full flex justify-end mb-2">
|
||||||
|
<button id="accept-terms-button" class="button button-primary bg-primary hover:bg-primary-darken">{{ ctrans('texts.next') }}</button>
|
||||||
|
</div>
|
||||||
|
<span class="text-xs text-gray-600 text-right">{{ ctrans('texts.by_clicking_next_you_accept_terms')}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
<div x-text="errors" class="alert alert-failure mb-4"></div>
|
<div x-text="errors" class="alert alert-failure mb-4"></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@if($settings->client_portal_allow_under_payment)
|
@if($settings->client_portal_allow_under_payment && $settings->client_portal_under_payment_minimum != 0)
|
||||||
<span class="mt-1 text-sm text-gray-800">{{ ctrans('texts.minimum_payment') }}:
|
<span class="mt-1 text-sm text-gray-800">{{ ctrans('texts.minimum_payment') }}:
|
||||||
{{ $settings->client_portal_under_payment_minimum }}</span>
|
{{ $settings->client_portal_under_payment_minimum }}</span>
|
||||||
@endif
|
@endif
|
||||||
|
@ -2,9 +2,17 @@
|
|||||||
|
|
||||||
@section('gateway_head')
|
@section('gateway_head')
|
||||||
<meta name="instant-payment" content="yes" />
|
<meta name="instant-payment" content="yes" />
|
||||||
|
<meta name="public_key" content="{{ $public_key }}" />
|
||||||
|
<meta name="gateway_id" content="{{ $gateway_id }}" />
|
||||||
|
<meta name="store_route" content="{{ route('client.payment_methods.store', ['method' => App\Models\GatewayType::CREDIT_CARD]) }}" />
|
||||||
|
<meta name="environment" content="{{ $environment }}" />
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('gateway_content')
|
@section('gateway_content')
|
||||||
|
<form action="javascript:void(0);" id="stepone">
|
||||||
|
<input type="hidden" name="gateway_response">
|
||||||
|
<button type="submit" class="hidden" id="stepone_submit">Submit</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
<form action="{{ route('client.payment_methods.store', ['method' => App\Models\GatewayType::CREDIT_CARD]) }}" method="post" id="server-response">
|
<form action="{{ route('client.payment_methods.store', ['method' => App\Models\GatewayType::CREDIT_CARD]) }}" method="post" id="server-response">
|
||||||
@csrf
|
@csrf
|
||||||
@ -18,7 +26,7 @@
|
|||||||
|
|
||||||
<div class="alert alert-failure mb-4" hidden id="errors"></div>
|
<div class="alert alert-failure mb-4" hidden id="errors"></div>
|
||||||
|
|
||||||
<div id="powerboard-payment-container" class="w-full">
|
<div id="powerboard-payment-container" class="w-full p-4" style="background-color: rgb(249, 249, 249);">
|
||||||
<div id="widget" style="block"></div>
|
<div id="widget" style="block"></div>
|
||||||
<div id="widget-3dsecure"></div>
|
<div id="widget-3dsecure"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -26,11 +34,9 @@
|
|||||||
@component('portal.ninja2020.gateways.includes.pay_now', ['id' => 'authorize-card'])
|
@component('portal.ninja2020.gateways.includes.pay_now', ['id' => 'authorize-card'])
|
||||||
{{ ctrans('texts.add_payment_method') }}
|
{{ ctrans('texts.add_payment_method') }}
|
||||||
@endcomponent
|
@endcomponent
|
||||||
|
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('gateway_footer')
|
@section('gateway_footer')
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
iframe {
|
iframe {
|
||||||
border: 0;
|
border: 0;
|
||||||
@ -41,203 +47,7 @@
|
|||||||
|
|
||||||
<script src="{{ $widget_endpoint }}"></script>
|
<script src="{{ $widget_endpoint }}"></script>
|
||||||
|
|
||||||
<script>
|
@vite('resources/js/clients/payment_methods/authorize-powerboard-card.js')
|
||||||
var widget = new cba.HtmlWidget('#widget', '{{ $public_key }}', '{{ $gateway_id }}');
|
|
||||||
widget.setEnv("{{ $environment }}");
|
|
||||||
widget.useAutoResize();
|
|
||||||
// widget.interceptSubmitForm('#server-response');
|
|
||||||
widget.onFinishInsert('input[name="gateway_response"]', "payment_source");
|
|
||||||
widget.load();
|
|
||||||
|
|
||||||
widget.trigger('tab', function (data){
|
|
||||||
|
|
||||||
console.log("tab Response", data);
|
|
||||||
|
|
||||||
console.log(widget.isValidForm());
|
|
||||||
|
|
||||||
let payNow = document.getElementById('pay-now');
|
|
||||||
|
|
||||||
payNow.disabled = widget.isInvalidForm();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.trigger('submit_form',function (data){
|
|
||||||
|
|
||||||
console.log("submit_form Response", data);
|
|
||||||
|
|
||||||
console.log(widget.isValidForm());
|
|
||||||
|
|
||||||
let payNow = document.getElementById('pay-now');
|
|
||||||
|
|
||||||
payNow.disabled = widget.isInvalidForm();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.trigger('tab',function (data){
|
|
||||||
|
|
||||||
console.log("tab Response", data);
|
|
||||||
|
|
||||||
console.log(widget.isValidForm());
|
|
||||||
|
|
||||||
let payNow = document.getElementById('pay-now');
|
|
||||||
|
|
||||||
payNow.disabled = widget.isInvalidForm();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.on("systemError", function(data) {
|
|
||||||
console.log("systemError Response", data);
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.on("validationError", function(data) {
|
|
||||||
console.log("validationError", data);
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.on("finish", async function(data) {
|
|
||||||
document.getElementById('errors').hidden = true;
|
|
||||||
|
|
||||||
console.log("finish", data);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const resource = await get3dsToken();
|
|
||||||
console.log("3DS Token:", resource);
|
|
||||||
|
|
||||||
console.log("pre canvas");
|
|
||||||
console.log(resource._3ds.token);
|
|
||||||
|
|
||||||
var canvas = new cba.Canvas3ds('#widget-3dsecure', resource._3ds.token);
|
|
||||||
canvas.load();
|
|
||||||
|
|
||||||
let widget = document.getElementById('widget');
|
|
||||||
widget.classList.add('hidden');
|
|
||||||
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching 3DS Token:", error);
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas.on("chargeAuthSuccess", function(data) {
|
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
document.querySelector(
|
|
||||||
'input[name="browser_details"]'
|
|
||||||
).value = null;
|
|
||||||
|
|
||||||
document.querySelector(
|
|
||||||
'input[name="charge"]'
|
|
||||||
).value = JSON.stringify(data);
|
|
||||||
|
|
||||||
document.getElementById('server-response').submit();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
canvas.on("chargeAuthReject", function(data) {
|
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
document.getElementById('errors').textContent = `Sorry, your transaction could not be processed...`;
|
|
||||||
document.getElementById('errors').hidden = false;
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
canvas.load();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.on("submit", async function (data){
|
|
||||||
console.log("submit");
|
|
||||||
console.log(data);
|
|
||||||
document.getElementById('errors').hidden = true;
|
|
||||||
})
|
|
||||||
|
|
||||||
widget.on('form_submit', function (data) {
|
|
||||||
console.log("form_submit", data);
|
|
||||||
console.log(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.on('submit', function (data) {
|
|
||||||
console.log("submit", data);
|
|
||||||
console.log(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.on('tab', function (data) {
|
|
||||||
console.log("tab", data);
|
|
||||||
console.log(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
let payNow = document.getElementById('authorize-card');
|
|
||||||
|
|
||||||
payNow.addEventListener('click', () => {
|
|
||||||
|
|
||||||
payNow.disabled = true;
|
|
||||||
payNow.querySelector('svg').classList.remove('hidden');
|
|
||||||
payNow.querySelector('span').classList.add('hidden');
|
|
||||||
|
|
||||||
document.getElementById('server-response').submit();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
async function get3dsToken() {
|
|
||||||
|
|
||||||
const browserDetails = {
|
|
||||||
name: navigator.userAgent.substring(0, 100), // The full user agent string, which contains the browser name and version
|
|
||||||
java_enabled: navigator.javaEnabled() ? "true" : "false", // Indicates if Java is enabled in the browser
|
|
||||||
language: navigator.language || navigator.userLanguage, // The browser language
|
|
||||||
screen_height: window.screen.height.toString(), // Screen height in pixels
|
|
||||||
screen_width: window.screen.width.toString(), // Screen width in pixels
|
|
||||||
time_zone: (new Date().getTimezoneOffset() * -1).toString(), // Timezone offset in minutes (negative for behind UTC)
|
|
||||||
color_depth: window.screen.colorDepth.toString() // Color depth in bits per pixel
|
|
||||||
};
|
|
||||||
|
|
||||||
document.querySelector(
|
|
||||||
'input[name="browser_details"]'
|
|
||||||
).value = JSON.stringify(browserDetails);
|
|
||||||
|
|
||||||
const formData = JSON.stringify(Object.fromEntries(new FormData(document.getElementById("server-response"))));
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Return the fetch promise to handle it externally
|
|
||||||
const response = await fetch('{{ route('client.payment_methods.store', ['method' => App\Models\GatewayType::CREDIT_CARD]) }}', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
"X-Requested-With": "XMLHttpRequest",
|
|
||||||
"Accept": 'application/json',
|
|
||||||
"X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').content
|
|
||||||
},
|
|
||||||
body: formData
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
|
|
||||||
return await response.json().then(errorData => {
|
|
||||||
throw new Error(errorData.message ?? 'Unknown error.');
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return await response.json()
|
|
||||||
|
|
||||||
}
|
|
||||||
catch(error) {
|
|
||||||
|
|
||||||
document.getElementById('errors').textContent = `Sorry, your card could not be authorized...\n\n${error.message}`;
|
|
||||||
document.getElementById('errors').hidden = false;
|
|
||||||
|
|
||||||
console.error('Fetch error:', error); // Log error for debugging
|
|
||||||
throw error; //
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const first = document.querySelector('input[name="payment-type"]');
|
|
||||||
|
|
||||||
if (first) {
|
|
||||||
first.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,140 +0,0 @@
|
|||||||
@extends('portal.ninja2020.layout.payments', ['gateway_title' => 'Credit card', 'card_title' => 'Credit card'])
|
|
||||||
|
|
||||||
@section('gateway_head')
|
|
||||||
<meta name="instant-payment" content="yes" />
|
|
||||||
@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="gateway_response">
|
|
||||||
<input type="hidden" name="company_gateway_id" value="{{ $gateway->getCompanyGatewayId() }}">
|
|
||||||
<input type="hidden" name="payment_method_id" value="{{ $payment_method_id }}">
|
|
||||||
<input type="hidden" name="charge_no3d">
|
|
||||||
<button type="submit" class="hidden" id="stub">Submit</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<div class="alert alert-failure mb-4" hidden id="errors"></div>
|
|
||||||
|
|
||||||
<div id="powerboard-payment-container" class="w-full">
|
|
||||||
<div id="widget" style="block"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@component('portal.ninja2020.gateways.includes.pay_now', ['id' => 'authorize-card'])
|
|
||||||
{{ ctrans('texts.add_payment_method') }}
|
|
||||||
@endcomponent
|
|
||||||
|
|
||||||
@endsection
|
|
||||||
|
|
||||||
@section('gateway_footer')
|
|
||||||
|
|
||||||
<style>
|
|
||||||
iframe {
|
|
||||||
border: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 400px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<script src="{{ $widget_endpoint }}"></script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var widget = new cba.HtmlWidget('#widget', '{{ $public_key }}', '{{ $gateway_id }}');
|
|
||||||
widget.setEnv("{{ $environment }}");
|
|
||||||
widget.useAutoResize();
|
|
||||||
widget.interceptSubmitForm('#server-response');
|
|
||||||
widget.onFinishInsert('input[name="gateway_response"]', "payment_source");
|
|
||||||
widget.load();
|
|
||||||
|
|
||||||
widget.trigger('tab', function (data){
|
|
||||||
|
|
||||||
console.log("tab Response", data);
|
|
||||||
|
|
||||||
console.log(widget.isValidForm());
|
|
||||||
|
|
||||||
let payNow = document.getElementById('pay-now');
|
|
||||||
|
|
||||||
payNow.disabled = widget.isInvalidForm();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.trigger('submit_form',function (data){
|
|
||||||
|
|
||||||
console.log("submit_form Response", data);
|
|
||||||
|
|
||||||
console.log(widget.isValidForm());
|
|
||||||
|
|
||||||
let payNow = document.getElementById('pay-now');
|
|
||||||
|
|
||||||
payNow.disabled = widget.isInvalidForm();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.trigger('tab',function (data){
|
|
||||||
|
|
||||||
console.log("tab Response", data);
|
|
||||||
|
|
||||||
console.log(widget.isValidForm());
|
|
||||||
|
|
||||||
let payNow = document.getElementById('pay-now');
|
|
||||||
|
|
||||||
payNow.disabled = widget.isInvalidForm();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.on("systemError", function(data) {
|
|
||||||
console.log("systemError Response", data);
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.on("validationError", function(data) {
|
|
||||||
console.log("validationError", data);
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.on("finish", async function(data) {
|
|
||||||
document.getElementById('errors').hidden = true;
|
|
||||||
console.log("finish", data);
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.on("submit", async function (data){
|
|
||||||
console.log("submit");
|
|
||||||
console.log(data);
|
|
||||||
document.getElementById('errors').hidden = true;
|
|
||||||
})
|
|
||||||
|
|
||||||
widget.on('form_submit', function (data) {
|
|
||||||
console.log("form_submit", data);
|
|
||||||
console.log(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.on('submit', function (data) {
|
|
||||||
console.log("submit", data);
|
|
||||||
console.log(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.on('tab', function (data) {
|
|
||||||
console.log("tab", data);
|
|
||||||
console.log(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
let payNow = document.getElementById('authorize-card');
|
|
||||||
|
|
||||||
payNow.addEventListener('click', () => {
|
|
||||||
|
|
||||||
document.querySelector(
|
|
||||||
'input[name="charge_no3d"]'
|
|
||||||
).value = true;
|
|
||||||
payNow.disabled = true;
|
|
||||||
payNow.querySelector('svg').classList.remove('hidden');
|
|
||||||
payNow.querySelector('span').classList.add('hidden');
|
|
||||||
|
|
||||||
document.getElementById('stub').click();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
@endsection
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
@section('gateway_head')
|
@section('gateway_head')
|
||||||
<meta name="instant-payment" content="yes" />
|
<meta name="instant-payment" content="yes" />
|
||||||
|
<meta name="public_key" content="{{ $public_key }}" />
|
||||||
|
<meta name="gateway_id" content="{{ $gateway_id }}" />
|
||||||
|
<meta name="environment" content="{{ $environment }}">
|
||||||
|
<meta name="payments_route" content="{{ route('client.payments.response') }}" />
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('gateway_content')
|
@section('gateway_content')
|
||||||
@ -23,6 +27,7 @@
|
|||||||
<input type="hidden" name="token">
|
<input type="hidden" name="token">
|
||||||
<input type="hidden" name="browser_details">
|
<input type="hidden" name="browser_details">
|
||||||
<input type="hidden" name="charge">
|
<input type="hidden" name="charge">
|
||||||
|
<input type="hidden" name="charge_3ds_id">
|
||||||
<button type="submit" class="hidden" id="stub">Submit</button>
|
<button type="submit" class="hidden" id="stub">Submit</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
@ -65,14 +70,14 @@
|
|||||||
</ul>
|
</ul>
|
||||||
@endcomponent
|
@endcomponent
|
||||||
|
|
||||||
<div id="powerboard-payment-container" class="w-full">
|
@include('portal.ninja2020.gateways.includes.save_card')
|
||||||
|
|
||||||
|
<div id="powerboard-payment-container" class="w-full p-4 hidden" style="background-color: rgb(249, 249, 249);">
|
||||||
<div id="widget" style="block" class="hidden"></div>
|
<div id="widget" style="block" class="hidden"></div>
|
||||||
<div id="widget-3dsecure"></div>
|
<div id="widget-3dsecure"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@include('portal.ninja2020.gateways.includes.save_card')
|
|
||||||
@include('portal.ninja2020.gateways.includes.pay_now')
|
@include('portal.ninja2020.gateways.includes.pay_now')
|
||||||
|
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('gateway_footer')
|
@section('gateway_footer')
|
||||||
@ -87,250 +92,7 @@
|
|||||||
|
|
||||||
<script src="{{ $widget_endpoint }}"></script>
|
<script src="{{ $widget_endpoint }}"></script>
|
||||||
|
|
||||||
<script>
|
@vite('resources/js/clients/payments/powerboard-credit-card.js')
|
||||||
|
|
||||||
/** Loads the widget, links the widget to a dummy form */
|
|
||||||
var widget = new cba.HtmlWidget('#widget', '{{ $public_key }}', '{{ $gateway_id }}');
|
|
||||||
widget.setEnv("{{ $environment }}");
|
|
||||||
widget.useAutoResize();
|
|
||||||
widget.interceptSubmitForm('#stepone');
|
|
||||||
widget.onFinishInsert('#server-response input[name="gateway_response"]', "payment_source");
|
|
||||||
widget.load();
|
|
||||||
|
|
||||||
widget.on("systemError", function(data) {
|
|
||||||
console.log("systemError Response", data);
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.on("validationError", function(data) {
|
|
||||||
console.log("validationError", data);
|
|
||||||
});
|
|
||||||
|
|
||||||
/** Retrieves the payment_source token and passes this to the 3ds handler */
|
|
||||||
widget.on("finish", function(data) {
|
|
||||||
document.getElementById('errors').hidden = true;
|
|
||||||
|
|
||||||
console.log("finish");
|
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
process3ds();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.on("submit", function (data){
|
|
||||||
console.log("submit");
|
|
||||||
console.log(data);
|
|
||||||
document.getElementById('errors').hidden = true;
|
|
||||||
})
|
|
||||||
|
|
||||||
widget.on('form_submit', function (data) {
|
|
||||||
console.log("form_submit", data);
|
|
||||||
console.log(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.on('tab', function (data) {
|
|
||||||
console.log("tab", data);
|
|
||||||
console.log(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
let payNow = document.getElementById('pay-now');
|
|
||||||
|
|
||||||
payNow.addEventListener('click', () => {
|
|
||||||
|
|
||||||
|
|
||||||
const div = document.getElementById('widget');
|
|
||||||
|
|
||||||
widget.getValidationState();
|
|
||||||
|
|
||||||
if(!widget.isValidForm() && div.offsetParent !== null){
|
|
||||||
console.log("invalid");
|
|
||||||
payNow.disabled = false;
|
|
||||||
payNow.querySelector('svg').classList.add('hidden');
|
|
||||||
payNow.querySelector('span').classList.remove('hidden');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
payNow.disabled = true;
|
|
||||||
payNow.querySelector('svg').classList.remove('hidden');
|
|
||||||
payNow.querySelector('span').classList.add('hidden');
|
|
||||||
|
|
||||||
let storeCard = document.querySelector(
|
|
||||||
'input[name=token-billing-checkbox]:checked'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (storeCard) {
|
|
||||||
document.getElementById('store_card').value = storeCard.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(div.offsetParent !== null)
|
|
||||||
document.getElementById('stepone_submit').click();
|
|
||||||
else
|
|
||||||
document.getElementById('server-response').submit();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
async function process3ds()
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
|
||||||
const resource = await get3dsToken();
|
|
||||||
console.log("3DS Token:", resource);
|
|
||||||
|
|
||||||
console.log("pre canvas");
|
|
||||||
console.log(resource._3ds.token);
|
|
||||||
|
|
||||||
if (resource.status == "not_authenticated" || resource.status == "authentication_not_supported") { // if status = authentication_not_supported, there will be no resource._3ds.token, so we need to fall back to a NON 3ds payment flow from here
|
|
||||||
throw new Error('There was an issue authenticating this payment method.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var canvas = new cba.Canvas3ds('#widget-3dsecure', resource._3ds.token);
|
|
||||||
canvas.load();
|
|
||||||
|
|
||||||
let widget = document.getElementById('widget');
|
|
||||||
widget.classList.add('hidden');
|
|
||||||
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching 3DS Token:", error);
|
|
||||||
|
|
||||||
document.getElementById('errors').textContent = `Sorry, your transaction could not be processed...\n\n${error}`;
|
|
||||||
document.getElementById('errors').hidden = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
canvas.on("chargeAuthSuccess", function(data) {
|
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
document.querySelector(
|
|
||||||
'input[name="browser_details"]'
|
|
||||||
).value = null;
|
|
||||||
|
|
||||||
document.querySelector(
|
|
||||||
'input[name="charge"]'
|
|
||||||
).value = JSON.stringify(data);
|
|
||||||
|
|
||||||
let storeCard = document.querySelector(
|
|
||||||
'input[name=token-billing-checkbox]:checked'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (storeCard) {
|
|
||||||
document.getElementById('store_card').value = storeCard.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById('server-response').submit();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
canvas.on("chargeAuthReject", function(data) {
|
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
document.getElementById('errors').textContent = `Sorry, your transaction could not be processed...`;
|
|
||||||
document.getElementById('errors').hidden = false;
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
canvas.load();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async function get3dsToken() {
|
|
||||||
|
|
||||||
const browserDetails = {
|
|
||||||
name: navigator.userAgent.substring(0, 100), // The full user agent string, which contains the browser name and version
|
|
||||||
java_enabled: navigator.javaEnabled() ? "true" : "false", // Indicates if Java is enabled in the browser
|
|
||||||
language: navigator.language || navigator.userLanguage, // The browser language
|
|
||||||
screen_height: window.screen.height.toString(), // Screen height in pixels
|
|
||||||
screen_width: window.screen.width.toString(), // Screen width in pixels
|
|
||||||
time_zone: (new Date().getTimezoneOffset() * -1).toString(), // Timezone offset in minutes (negative for behind UTC)
|
|
||||||
color_depth: window.screen.colorDepth.toString() // Color depth in bits per pixel
|
|
||||||
};
|
|
||||||
|
|
||||||
document.querySelector(
|
|
||||||
'input[name="browser_details"]'
|
|
||||||
).value = JSON.stringify(browserDetails);
|
|
||||||
|
|
||||||
const formData = JSON.stringify(Object.fromEntries(new FormData(document.getElementById("server-response"))));
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Return the fetch promise to handle it externally
|
|
||||||
const response = await fetch('{{ route('client.payments.response') }}', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
"X-Requested-With": "XMLHttpRequest",
|
|
||||||
"Accept": 'application/json',
|
|
||||||
"X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').content
|
|
||||||
},
|
|
||||||
body: formData
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
|
|
||||||
return await response.json().then(errorData => {
|
|
||||||
throw new Error(errorData.message ?? 'Unknown error.');
|
|
||||||
});
|
|
||||||
|
|
||||||
// const text = await response.text();
|
|
||||||
// throw new Error(`Network response was not ok: ${response.statusText}. Response text: ${text}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await response.json()
|
|
||||||
|
|
||||||
}
|
|
||||||
catch(error) {
|
|
||||||
|
|
||||||
document.getElementById('errors').textContent = `Sorry, your transaction could not be processed...\n\n${error.message}`;
|
|
||||||
document.getElementById('errors').hidden = false;
|
|
||||||
|
|
||||||
console.error('Fetch error:', error); // Log error for debugging
|
|
||||||
throw error; //
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const first = document.querySelector('input[name="payment-type"]');
|
|
||||||
|
|
||||||
if (first) {
|
|
||||||
first.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
document
|
|
||||||
.getElementById('toggle-payment-with-credit-card')
|
|
||||||
.addEventListener('click', (element) => {
|
|
||||||
|
|
||||||
let widget = document.getElementById('widget');
|
|
||||||
widget.classList.remove('hidden');
|
|
||||||
document.getElementById('save-card--container').style.display ='grid';
|
|
||||||
document.querySelector('input[name=token]').value = '';
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
Array.from(
|
|
||||||
document.getElementsByClassName('toggle-payment-with-token')
|
|
||||||
).forEach((element) =>
|
|
||||||
element.addEventListener('click', (element) => {
|
|
||||||
document
|
|
||||||
.getElementById('widget')
|
|
||||||
.classList.add('hidden');
|
|
||||||
document.getElementById(
|
|
||||||
'save-card--container'
|
|
||||||
).style.display = 'none';
|
|
||||||
document.querySelector('input[name=token]').value =
|
|
||||||
element.target.dataset.token;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
<div class="rounded-lg border bg-card text-card-foreground shadow-sm overflow-hidden py-5 bg-white sm:gap-4"
|
||||||
|
id="powerboard-credit-card-payment">
|
||||||
|
<meta name="public_key" content="{{ $public_key }}" />
|
||||||
|
<meta name="gateway_id" content="{{ $gateway_id }}" />
|
||||||
|
<meta name="environment" content="{{ $environment }}">
|
||||||
|
<meta name="payments_route" content="{{ route('client.payments.response') }}" />
|
||||||
|
|
||||||
|
<form action="javascript:void(0);" id="stepone">
|
||||||
|
<input type="hidden" name="gateway_response">
|
||||||
|
<button type="submit" class="hidden" id="stepone_submit">Submit</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form action="{{ route('client.payments.response') }}" method="post" id="server-response">
|
||||||
|
@csrf
|
||||||
|
<input type="hidden" name="gateway_response">
|
||||||
|
<input type="hidden" name="store_card" id="store_card"/>
|
||||||
|
<input type="hidden" name="payment_hash" value="{{ $payment_hash }}">
|
||||||
|
|
||||||
|
<input type="hidden" name="company_gateway_id" value="{{ $gateway->getCompanyGatewayId() }}">
|
||||||
|
<input type="hidden" name="payment_method_id" value="{{ $payment_method_id }}">
|
||||||
|
|
||||||
|
<input type="hidden" name="token">
|
||||||
|
<input type="hidden" name="browser_details">
|
||||||
|
<input type="hidden" name="charge">
|
||||||
|
<input type="hidden" name="charge_3ds_id">
|
||||||
|
<button type="submit" class="hidden" id="stub">Submit</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="alert alert-failure mb-4" hidden 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')])
|
||||||
|
<ul class="list-none">
|
||||||
|
@if(count($tokens) > 0)
|
||||||
|
@foreach($tokens as $token)
|
||||||
|
<li class="py-2 cursor-pointer">
|
||||||
|
<label class="mr-4">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
data-token="{{ $token->token }}"
|
||||||
|
name="payment-type"
|
||||||
|
class="form-check-input text-indigo-600 rounded-full cursor-pointer toggle-payment-with-token toggle-payment-with-token"/>
|
||||||
|
<span class="ml-1 cursor-pointer">**** {{ $token->meta?->last4 }}</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
@endforeach
|
||||||
|
@endisset
|
||||||
|
|
||||||
|
<li class="py-2 cursor-pointer">
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
id="toggle-payment-with-credit-card"
|
||||||
|
class="form-check-input text-indigo-600 rounded-full cursor-pointer"
|
||||||
|
name="payment-type"
|
||||||
|
checked/>
|
||||||
|
<span class="ml-1 cursor-pointer">{{ __('texts.new_card') }}</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
@endcomponent
|
||||||
|
|
||||||
|
@include('portal.ninja2020.gateways.includes.save_card')
|
||||||
|
|
||||||
|
<div id="powerboard-payment-container" class="w-full p-4 hidden" style="background-color: rgb(249, 249, 249);">
|
||||||
|
<div id="widget" style="block" class="hidden"></div>
|
||||||
|
<div id="widget-3dsecure"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@include('portal.ninja2020.gateways.includes.pay_now')
|
||||||
|
|
||||||
|
<style>
|
||||||
|
iframe {
|
||||||
|
border: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@assets
|
||||||
|
<script src="{{ $widget_endpoint }}"></script>
|
||||||
|
|
||||||
|
@vite('resources/js/clients/payments/powerboard-credit-card.js')
|
||||||
|
@endassets
|
@ -52,8 +52,8 @@
|
|||||||
Livewire.on('passed-required-fields-check', () => {
|
Livewire.on('passed-required-fields-check', () => {
|
||||||
|
|
||||||
document.querySelector('div[data-ref="required-fields-container"]').classList.toggle('h-0');
|
document.querySelector('div[data-ref="required-fields-container"]').classList.toggle('h-0');
|
||||||
// document.querySelector('div[data-ref="required-fields-container"]').classList.add('opacity-25');
|
document.querySelector('div[data-ref="required-fields-container"]').classList.add('opacity-25');
|
||||||
// document.querySelector('div[data-ref="required-fields-container"]').classList.add('pointer-events-none');
|
document.querySelector('div[data-ref="required-fields-container"]').classList.add('pointer-events-none');
|
||||||
|
|
||||||
document.querySelector('div[data-ref="gateway-container"]').classList.remove('opacity-25');
|
document.querySelector('div[data-ref="gateway-container"]').classList.remove('opacity-25');
|
||||||
document.querySelector('div[data-ref="gateway-container"]').classList.remove('pointer-events-none');
|
document.querySelector('div[data-ref="gateway-container"]').classList.remove('pointer-events-none');
|
||||||
|
@ -16,10 +16,10 @@
|
|||||||
<dl>
|
<dl>
|
||||||
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||||
<dt class="text-sm leading-5 font-medium text-gray-500">
|
<dt class="text-sm leading-5 font-medium text-gray-500">
|
||||||
{{ ctrans('texts.start_date') }}
|
{{ ctrans('texts.last_sent') }}
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||||
{{ $invoice->translateDate($invoice->start_date, $invoice->client->date_format(), $invoice->client->locale()) }}
|
{{ $invoice->translateDate($invoice->last_sent_date, $invoice->client->date_format(), $invoice->client->locale()) }}
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||||
|
@ -53,6 +53,8 @@ export default defineConfig({
|
|||||||
'resources/js/clients/payments/stripe-ach-pay.js',
|
'resources/js/clients/payments/stripe-ach-pay.js',
|
||||||
'resources/js/clients/payments/stripe-bank-transfer.js',
|
'resources/js/clients/payments/stripe-bank-transfer.js',
|
||||||
'resources/js/clients/payment_methods/authorize-stripe-acss.js',
|
'resources/js/clients/payment_methods/authorize-stripe-acss.js',
|
||||||
|
'resources/js/clients/payment_methods/authorize-powerboard-card.js',
|
||||||
|
'resources/js/clients/payments/powerboard-credit-card.js',
|
||||||
]),
|
]),
|
||||||
viteStaticCopy({
|
viteStaticCopy({
|
||||||
targets: [
|
targets: [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user