mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-08 00:04:29 -04:00
merge
This commit is contained in:
commit
20b04a266f
@ -17,7 +17,7 @@ use App\Models\Subscription;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
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 array $context;
|
||||
@ -28,10 +28,7 @@ class Methods extends Component
|
||||
{
|
||||
$total = collect($this->context['products'])->sum('total_raw');
|
||||
|
||||
$methods = auth()->guard('contact')->user()->client->service()->getPaymentMethods(
|
||||
$total,
|
||||
);
|
||||
|
||||
$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()
|
||||
$this->methods = $methods;
|
||||
}
|
||||
|
||||
|
@ -199,6 +199,7 @@ class BillingPortalPurchasev2 extends Component
|
||||
$this->data = [];
|
||||
|
||||
$this->price = $this->subscription->price; // ?
|
||||
$this->float_amount_total = $this->price;
|
||||
|
||||
$this->recurring_products = $this->subscription->service()->recurring_products();
|
||||
$this->products = $this->subscription->service()->products();
|
||||
@ -244,7 +245,8 @@ class BillingPortalPurchasev2 extends Component
|
||||
Auth::guard('contact')->loginUsingId($contact->id, true);
|
||||
$this->contact = $contact;
|
||||
} else {
|
||||
$this->createClientContact();
|
||||
// $this->createClientContact();
|
||||
$this->createBlankClient();
|
||||
}
|
||||
|
||||
$this->getPaymentMethods();
|
||||
@ -767,6 +769,8 @@ class BillingPortalPurchasev2 extends Component
|
||||
if ($currency) {
|
||||
$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)) {
|
||||
@ -785,8 +789,12 @@ class BillingPortalPurchasev2 extends Component
|
||||
}
|
||||
|
||||
$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');
|
||||
|
||||
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.
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
@ -194,13 +194,14 @@ class RequiredClientInfo extends Component
|
||||
|
||||
public function mount()
|
||||
{
|
||||
|
||||
MultiDB::setDb($this->db);
|
||||
|
||||
$contact = ClientContact::withTrashed()->with(['client' => function ($query) {
|
||||
$query->without('gateway_tokens', 'documents', 'contacts.company', 'contacts'); // Exclude 'grandchildren' relation of 'client'
|
||||
}])->find($this->contact_id);
|
||||
|
||||
$this->company_gateway = CompanyGateway::withTrashed()->with('company')->find($this->company_gateway_id);
|
||||
|
||||
$company = $this->company_gateway->company;
|
||||
|
||||
$this->client_name = $contact->client->name;
|
||||
@ -240,6 +241,13 @@ class RequiredClientInfo extends Component
|
||||
$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)) {
|
||||
$this->show_form = true;
|
||||
}
|
||||
@ -385,7 +393,6 @@ class RequiredClientInfo extends Component
|
||||
|
||||
public function checkFields()
|
||||
{
|
||||
|
||||
MultiDB::setDb($this->db);
|
||||
$_contact = ClientContact::withTrashed()->find($this->contact_id);
|
||||
|
||||
|
@ -25,6 +25,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
* @property int $user_id
|
||||
* @property int|null $assigned_user_id
|
||||
* @property int $company_id
|
||||
* @property int $remaining_cycles
|
||||
* @property string|null $product_ids
|
||||
* @property int|null $frequency_id
|
||||
* @property string|null $auto_bill
|
||||
@ -117,6 +118,7 @@ class Subscription extends BaseModel
|
||||
'optional_recurring_product_ids',
|
||||
'use_inventory_management',
|
||||
'steps',
|
||||
'remaining_cycles',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
|
@ -39,9 +39,9 @@ class CreditCard implements LivewireMethodInterface
|
||||
public function authorizeView(array $data)
|
||||
{
|
||||
$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($view, $this->paymentData($data));
|
||||
return render('gateways.powerboard.credit_card.authorize', $this->paymentData($data));
|
||||
}
|
||||
|
||||
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, []);
|
||||
|
||||
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();
|
||||
@ -93,7 +97,7 @@ class CreditCard implements LivewireMethodInterface
|
||||
|
||||
$payload = [
|
||||
'_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,
|
||||
"authorization" => true,
|
||||
@ -215,6 +219,8 @@ class CreditCard implements LivewireMethodInterface
|
||||
|
||||
public function paymentData(array $data): array
|
||||
{
|
||||
$this->powerboard->init();
|
||||
|
||||
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);
|
||||
|
||||
@ -260,11 +266,8 @@ class CreditCard implements LivewireMethodInterface
|
||||
nlog($r->body());
|
||||
|
||||
if($r->failed()){
|
||||
|
||||
$error_payload = $this->getErrorFromResponse($r);
|
||||
|
||||
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();
|
||||
@ -303,7 +306,8 @@ class CreditCard implements LivewireMethodInterface
|
||||
$r = $this->powerboard->gatewayRequest('/v1/charges/3ds', (\App\Enum\HttpVerb::POST)->value, $payload, []);
|
||||
|
||||
if ($r->failed()) {
|
||||
return $this->processUnsuccessfulPayment($r);
|
||||
$error_payload = $this->getErrorFromResponse($r);
|
||||
return response()->json(['message' => $error_payload[0]], 400);
|
||||
}
|
||||
|
||||
$charge = $r->json();
|
||||
@ -351,7 +355,7 @@ class CreditCard implements LivewireMethodInterface
|
||||
|
||||
$payload = [
|
||||
'_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
|
||||
"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)
|
||||
@ -442,6 +449,7 @@ class CreditCard implements LivewireMethodInterface
|
||||
$error_message = "Unknown error";
|
||||
|
||||
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,
|
||||
"UnfulfilledCondition" => $error_message = $error_object->error->message,
|
||||
"transaction_declined" => $error_message = $error_object->error->details[0]->status_code_description,
|
||||
@ -455,11 +463,29 @@ class CreditCard implements LivewireMethodInterface
|
||||
}
|
||||
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
|
||||
{
|
||||
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)
|
||||
|
@ -1055,8 +1055,8 @@ class SubscriptionService
|
||||
$recurring_invoice->line_items = $subscription_repo->generateLineItems($this->subscription, true, false);
|
||||
$recurring_invoice->subscription_id = $this->subscription->id;
|
||||
$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->remaining_cycles = -1;
|
||||
$recurring_invoice->auto_bill = $client->getSetting('auto_bill');
|
||||
$recurring_invoice->auto_bill_enabled = $this->setAutoBillFlag($recurring_invoice->auto_bill);
|
||||
$recurring_invoice->due_date_days = 'terms';
|
||||
@ -1089,7 +1089,7 @@ class SubscriptionService
|
||||
$recurring_invoice->subscription_id = $this->subscription->id;
|
||||
$recurring_invoice->frequency_id = $this->subscription->frequency_id ?: RecurringInvoice::FREQUENCY_MONTHLY;
|
||||
$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_enabled = $this->setAutoBillFlag($recurring_invoice->auto_bill);
|
||||
$recurring_invoice->due_date_days = 'terms';
|
||||
|
@ -73,6 +73,7 @@ class SubscriptionTransformer extends EntityTransformer
|
||||
'optional_product_ids' => (string) $subscription->optional_product_ids,
|
||||
'registration_required' => (bool) $subscription->registration_required,
|
||||
'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.',
|
||||
'pay_with' => 'Pay with',
|
||||
'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',
|
||||
'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.',
|
||||
|
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,
|
||||
"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": {
|
||||
"file": "assets/authorize-stripe-acss-f6bd46c1.js",
|
||||
"imports": [
|
||||
@ -141,6 +149,14 @@
|
||||
"isEntry": true,
|
||||
"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": {
|
||||
"file": "assets/razorpay-aio-f8e8c7f0.js",
|
||||
"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>
|
||||
</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>
|
||||
<h2 class="text-2xl font-bold tracking-wide border-b-2 pb-4">{{ $heading_text ?? ctrans('texts.checkout') }}</h2>
|
||||
@if (session()->has('message'))
|
||||
|
@ -13,8 +13,11 @@
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end items-center 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="flex flex-col items-end px-4 py-4">
|
||||
<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>
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
<div x-text="errors" class="alert alert-failure mb-4"></div>
|
||||
</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') }}:
|
||||
{{ $settings->client_portal_under_payment_minimum }}</span>
|
||||
@endif
|
||||
|
@ -2,9 +2,17 @@
|
||||
|
||||
@section('gateway_head')
|
||||
<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
|
||||
|
||||
@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">
|
||||
@csrf
|
||||
@ -18,7 +26,7 @@
|
||||
|
||||
<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-3dsecure"></div>
|
||||
</div>
|
||||
@ -26,11 +34,9 @@
|
||||
@component('portal.ninja2020.gateways.includes.pay_now', ['id' => 'authorize-card'])
|
||||
{{ ctrans('texts.add_payment_method') }}
|
||||
@endcomponent
|
||||
|
||||
@endsection
|
||||
|
||||
@section('gateway_footer')
|
||||
|
||||
<style>
|
||||
iframe {
|
||||
border: 0;
|
||||
@ -41,203 +47,7 @@
|
||||
|
||||
<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);
|
||||
|
||||
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>
|
||||
|
||||
@vite('resources/js/clients/payment_methods/authorize-powerboard-card.js')
|
||||
@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')
|
||||
<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
|
||||
|
||||
@section('gateway_content')
|
||||
@ -23,6 +27,7 @@
|
||||
<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>
|
||||
|
||||
@ -65,14 +70,14 @@
|
||||
</ul>
|
||||
@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-3dsecure"></div>
|
||||
</div>
|
||||
|
||||
@include('portal.ninja2020.gateways.includes.save_card')
|
||||
@include('portal.ninja2020.gateways.includes.pay_now')
|
||||
|
||||
@endsection
|
||||
|
||||
@section('gateway_footer')
|
||||
@ -87,250 +92,7 @@
|
||||
|
||||
<script src="{{ $widget_endpoint }}"></script>
|
||||
|
||||
<script>
|
||||
|
||||
/** 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>
|
||||
|
||||
@vite('resources/js/clients/payments/powerboard-credit-card.js')
|
||||
@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', () => {
|
||||
|
||||
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('pointer-events-none');
|
||||
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="gateway-container"]').classList.remove('opacity-25');
|
||||
document.querySelector('div[data-ref="gateway-container"]').classList.remove('pointer-events-none');
|
||||
|
@ -16,10 +16,10 @@
|
||||
<dl>
|
||||
<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">
|
||||
{{ ctrans('texts.start_date') }}
|
||||
{{ ctrans('texts.last_sent') }}
|
||||
</dt>
|
||||
<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>
|
||||
</div>
|
||||
<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-bank-transfer.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({
|
||||
targets: [
|
||||
|
Loading…
x
Reference in New Issue
Block a user