Merge pull request #4182 from beganovich/v2-frontend-refactor

(v5) Refactor gateway front-ends
This commit is contained in:
David Bomba 2020-11-02 07:34:38 +11:00 committed by GitHub
commit 175911d0f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
64 changed files with 1703 additions and 1056 deletions

View File

@ -15,6 +15,7 @@ namespace App\Http\Controllers\ClientPortal;
use App\Events\Payment\Methods\MethodDeleted; use App\Events\Payment\Methods\MethodDeleted;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Http\Requests\ClientPortal\CreatePaymentMethodRequest; use App\Http\Requests\ClientPortal\CreatePaymentMethodRequest;
use App\Http\Requests\Request;
use App\Models\ClientGatewayToken; use App\Models\ClientGatewayToken;
use App\Models\CompanyGateway; use App\Models\CompanyGateway;
use App\Models\GatewayType; use App\Models\GatewayType;
@ -24,8 +25,6 @@ use App\Utils\Traits\MakesDates;
use Exception; use Exception;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\View\View; use Illuminate\View\View;
@ -123,14 +122,14 @@ class PaymentMethodController extends Controller
->verificationView($payment_method); ->verificationView($payment_method);
} }
public function processVerification(ClientGatewaytoken $payment_method) public function processVerification(Request $request, ClientGatewaytoken $payment_method)
{ {
$gateway = $this->getClientGateway(); $gateway = $this->getClientGateway();
return $gateway return $gateway
->driver(auth()->user()->client) ->driver(auth()->user()->client)
->setPaymentMethod(request()->query('method')) ->setPaymentMethod(request()->query('method'))
->processVerification($payment_method); ->processVerification($request, $payment_method);
} }
/** /**

View File

@ -36,4 +36,19 @@ class PaymentResponseRequest extends FormRequest
return PaymentHash::whereRaw('BINARY `hash`= ?', [$input['payment_hash']])->first(); return PaymentHash::whereRaw('BINARY `hash`= ?', [$input['payment_hash']])->first();
} }
public function prepareForValidation()
{
if ($this->has('store_card')) {
$this->merge([
'store_card' => ($this->store_card === "true" || $this->store_card === true) ? true : false,
]);
}
if ($this->has('pay_with_token')) {
$this->merge([
'pay_with_token' => ($this->pay_with_token === "true" || $this->pay_with_token === true) ? true : false,
]);
}
}
} }

View File

@ -171,7 +171,7 @@ class BaseDriver extends AbstractPaymentDriver
$payment->amount = $data['amount']; $payment->amount = $data['amount'];
$payment->type_id = $data['payment_type']; $payment->type_id = $data['payment_type'];
$payment->transaction_reference = $data['payment_method']; $payment->transaction_reference = $data['transaction_reference'];
$payment->client_contact_id = $client_contact_id; $payment->client_contact_id = $client_contact_id;
$payment->save(); $payment->save();
@ -272,7 +272,7 @@ class BaseDriver extends AbstractPaymentDriver
* @param array $data * @param array $data
* @return null|ClientGatewayToken * @return null|ClientGatewayToken
*/ */
public function storeGatewayToken(array $data): ?ClientGatewayToken public function storeGatewayToken(array $data, array $additional = []): ?ClientGatewayToken
{ {
$company_gateway_token = new ClientGatewayToken(); $company_gateway_token = new ClientGatewayToken();
$company_gateway_token->company_id = $this->client->company->id; $company_gateway_token->company_id = $this->client->company->id;
@ -281,6 +281,11 @@ class BaseDriver extends AbstractPaymentDriver
$company_gateway_token->company_gateway_id = $this->company_gateway->id; $company_gateway_token->company_gateway_id = $this->company_gateway->id;
$company_gateway_token->gateway_type_id = $data['payment_method_id']; $company_gateway_token->gateway_type_id = $data['payment_method_id'];
$company_gateway_token->meta = $data['payment_meta']; $company_gateway_token->meta = $data['payment_meta'];
foreach ($additional as $key => $value) {
$company_gateway_token->{$key} = $value;
}
$company_gateway_token->save(); $company_gateway_token->save();
if ($this->client->gateway_tokens->count() == 1) { if ($this->client->gateway_tokens->count() == 1) {

View File

@ -91,7 +91,7 @@ class CreditCard
$this->checkout->payment_hash->data = array_merge((array) $this->checkout->payment_hash->data, $state); $this->checkout->payment_hash->data = array_merge((array) $this->checkout->payment_hash->data, $state);
$this->checkout->payment_hash->save(); $this->checkout->payment_hash->save();
if ($request->has('token') && !is_null($request->token)) { if ($request->has('token') && !is_null($request->token) && $request->pay_with_token) {
return $this->attemptPaymentUsingToken($request); return $this->attemptPaymentUsingToken($request);
} }

View File

@ -60,6 +60,7 @@ trait Utilities
'payment_method' => $_payment->source['id'], 'payment_method' => $_payment->source['id'],
'payment_type' => PaymentType::parseCardType(strtolower($_payment->source['scheme'])), 'payment_type' => PaymentType::parseCardType(strtolower($_payment->source['scheme'])),
'amount' => $this->checkout->payment_hash->data->raw_value, 'amount' => $this->checkout->payment_hash->data->raw_value,
'transaction_reference' => $_payment->reference,
]; ];
$payment = $this->checkout->createPayment($data, \App\Models\Payment::STATUS_COMPLETED); $payment = $this->checkout->createPayment($data, \App\Models\Payment::STATUS_COMPLETED);

View File

@ -12,7 +12,8 @@
namespace App\PaymentDrivers\Stripe; namespace App\PaymentDrivers\Stripe;
use App\Events\Payment\PaymentWasCreated; use App\Exceptions\PaymentFailed;
use App\Http\Requests\Request;
use App\Jobs\Mail\PaymentFailureMailer; use App\Jobs\Mail\PaymentFailureMailer;
use App\Jobs\Util\SystemLogger; use App\Jobs\Util\SystemLogger;
use App\Models\ClientGatewayToken; use App\Models\ClientGatewayToken;
@ -21,10 +22,6 @@ use App\Models\Payment;
use App\Models\PaymentType; use App\Models\PaymentType;
use App\Models\SystemLog; use App\Models\SystemLog;
use App\PaymentDrivers\StripePaymentDriver; use App\PaymentDrivers\StripePaymentDriver;
use App\Utils\Ninja;
use Exception;
use Stripe\Customer;
use Stripe\Exception\CardException;
use Stripe\Exception\InvalidRequestException; use Stripe\Exception\InvalidRequestException;
use Stripe\StripeClient; use Stripe\StripeClient;
@ -45,54 +42,21 @@ class ACH
public function authorizeResponse($request) public function authorizeResponse($request)
{ {
$state = [ $this->stripe->init();
'server_response' => json_decode($request->gateway_response),
'gateway_id' => $request->company_gateway_id, $stripe_response = json_decode($request->input('gateway_response'));
'gateway_type_id' => $request->gateway_type_id,
'is_default' => $request->is_default,
];
$customer = $this->stripe->findOrCreateCustomer(); $customer = $this->stripe->findOrCreateCustomer();
$this->stripe->init();
$local_stripe = new StripeClient(
$this->stripe->company_gateway->getConfigField('apiKey')
);
try { try {
$local_stripe->customers->createSource( $source = $this->stripe->stripe->customers->createSource($customer->id, ['source' => $stripe_response->token->id]);
$customer->id,
['source' => $state['server_response']->token->id]
);
} catch (InvalidRequestException $e) { } catch (InvalidRequestException $e) {
return back()->with('ach_error', $e->getMessage()); throw new PaymentFailed($e->getMessage(), $e->getCode());
} }
$payment_meta = $state['server_response']->token->bank_account; $client_gateway_token = $this->storePaymentMethod($source, $request->input('method'), $customer);
$payment_meta->brand = ctrans('texts.ach');
$payment_meta->type = ctrans('texts.bank_transfer');
$payment_meta->verified_at = null;
$payment_meta->token = $state['server_response']->token->id;
$client_gateway_token = new ClientGatewayToken(); return redirect()->route('client.payment_methods.verification', ['payment_method' => $client_gateway_token->hashed_id, 'method' => GatewayType::BANK_TRANSFER]);
$client_gateway_token->company_id = $this->stripe->client->company->id;
$client_gateway_token->client_id = $this->stripe->client->id;
$client_gateway_token->token = $state['server_response']->token->bank_account->id;
$client_gateway_token->company_gateway_id = $this->stripe->company_gateway->id;
$client_gateway_token->gateway_type_id = $state['gateway_type_id'];
$client_gateway_token->gateway_customer_reference = $customer->id;
$client_gateway_token->meta = $payment_meta;
$client_gateway_token->save();
if ($state['is_default'] == 'true' || $this->stripe->client->gateway_tokens->count() == 1) {
$this->stripe->client->gateway_tokens()->update(['is_default' => 0]);
$client_gateway_token->is_default = 1;
$client_gateway_token->save();
}
return redirect()->route('client.payment_methods.verification', ['id' => $client_gateway_token->hashed_id, 'method' => GatewayType::BANK_TRANSFER]);
} }
public function verificationView(ClientGatewayToken $token) public function verificationView(ClientGatewayToken $token)
@ -100,14 +64,11 @@ class ACH
return render('gateways.stripe.ach.verify', compact('token')); return render('gateways.stripe.ach.verify', compact('token'));
} }
public function processVerification(ClientGatewayToken $token) public function processVerification(Request $request, ClientGatewayToken $token)
{ {
$this->stripe->init(); $this->stripe->init();
$bank_account = Customer::retrieveSource( $bank_account = \Stripe\Customer::retrieveSource($request->customer, $request->source);
request()->customer,
request()->source,
);
try { try {
$status = $bank_account->verify(['amounts' => request()->transactions]); $status = $bank_account->verify(['amounts' => request()->transactions]);
@ -125,38 +86,33 @@ class ACH
public function paymentView(array $data) public function paymentView(array $data)
{ {
$state = [ $data['gateway'] = $this->stripe;
'amount' => $data['amount_with_fee'], $data['currency'] = $this->stripe->client->getCurrencyCode();
'currency' => $this->stripe->client->getCurrencyCode(), $data['payment_method_id'] = GatewayType::BANK_TRANSFER;
'invoices' => $data['invoices'], $data['customer'] = $this->stripe->findOrCreateCustomer();
'gateway' => $this->stripe, $data['amount'] = $this->stripe->convertToStripeAmount($data['amount_with_fee'], $this->stripe->client->currency()->precision);
'payment_method_id' => GatewayType::BANK_TRANSFER,
'token' => $data['token'],
'customer' => $this->stripe->findOrCreateCustomer(),
];
return render('gateways.stripe.ach.pay', $state); return render('gateways.stripe.ach.pay', $data);
} }
public function paymentResponse($request) public function paymentResponse($request)
{ {
$this->stripe->init();
$state = [ $state = [
'payment_method' => $request->payment_method_id, 'payment_method' => $request->payment_method_id,
'gateway_type_id' => $request->company_gateway_id, 'gateway_type_id' => $request->company_gateway_id,
'hashed_ids' => $request->hashed_ids,
'amount' => $this->stripe->convertToStripeAmount($request->amount, $this->stripe->client->currency()->precision), 'amount' => $this->stripe->convertToStripeAmount($request->amount, $this->stripe->client->currency()->precision),
'currency' => $request->currency, 'currency' => $request->currency,
'source' => $request->source, 'source' => $request->source,
'customer' => $request->customer, 'customer' => $request->customer,
]; ];
if ($this->stripe->getContact()) { $state = array_merge($state, $request->all());
$state['client_contact'] = $this->stripe->getContact();
} else {
$state['client_contact'] = $state['invoices']->first()->invitations->first()->contact;
}
$this->stripe->init(); $this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, $state);
$this->stripe->payment_hash->save();
try { try {
$state['charge'] = \Stripe\Charge::create([ $state['charge'] = \Stripe\Charge::create([
@ -166,6 +122,11 @@ class ACH
'source' => $state['source'], 'source' => $state['source'],
]); ]);
$state = array_merge($state, $request->all());
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, $state);
$this->stripe->payment_hash->save();
if ($state['charge']->status === 'pending' && is_null($state['charge']->failure_message)) { if ($state['charge']->status === 'pending' && is_null($state['charge']->failure_message)) {
return $this->processPendingPayment($state); return $this->processPendingPayment($state);
} }
@ -180,33 +141,24 @@ class ACH
public function processPendingPayment($state) public function processPendingPayment($state)
{ {
$state['charge_id'] = $state['charge']->id;
$this->stripe->init(); $this->stripe->init();
$state['payment_type'] = PaymentType::ACH;
$data = [ $data = [
'payment_method' => $state['charge_id'], 'payment_method' => $state['source'],
'payment_type' => $state['payment_type'], 'payment_type' => PaymentType::ACH,
'amount' => $state['charge']->amount, 'amount' => $this->stripe->convertFromStripeAmount($this->stripe->payment_hash->data->amount, $this->stripe->client->currency()->precision),
'gateway_type_id' => GatewayType::BANK_TRANSFER, 'transaction_reference' => $state['charge']->id,
]; ];
$payment = $this->stripe->createPayment($data, Payment::STATUS_PENDING); $payment = $this->stripe->createPayment($data, Payment::STATUS_PENDING);
$this->stripe->attachInvoices($payment, $state['hashed_ids']); //todo remove hashed_ids SystemLogger::dispatch(
['response' => $state['charge'], 'data' => $data],
$payment->service()->updateInvoicePayment();//inject payment_hash SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_SUCCESS,
event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars())); SystemLog::TYPE_STRIPE,
$this->stripe->client
$logger_message = [ );
'server_response' => $state['charge'],
'data' => $data,
];
SystemLogger::dispatch($logger_message, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_STRIPE, $this->stripe->client);
return redirect()->route('client.payments.show', ['payment' => $this->stripe->encodePrimaryKey($payment->id)]); return redirect()->route('client.payments.show', ['payment' => $this->stripe->encodePrimaryKey($payment->id)]);
} }
@ -215,13 +167,46 @@ class ACH
{ {
PaymentFailureMailer::dispatch($this->stripe->client, $state['charge']->failure_message, $this->stripe->client->company, $state['amount']); PaymentFailureMailer::dispatch($this->stripe->client, $state['charge']->failure_message, $this->stripe->client->company, $state['amount']);
PaymentFailureMailer::dispatch(
$this->stripe->client,
$state['charge'],
$this->stripe->client->company,
$state['amount']
);
$message = [ $message = [
'server_response' => $state['charge'], 'server_response' => $state['charge'],
'data' => $state, 'data' => $this->stripe->payment_hash->data,
]; ];
SystemLogger::dispatch($message, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_STRIPE, $this->stripe->client); SystemLogger::dispatch(
$message,
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_FAILURE,
SystemLog::TYPE_STRIPE,
$this->stripe->client
);
throw new Exception('Failed to process the payment.', 1); throw new PaymentFailed('Failed to process the payment.', 500);
}
private function storePaymentMethod($method, $payment_method_id, $customer)
{
try {
$payment_meta = new \stdClass;
$payment_meta->brand = (string) sprintf('%s (%s)', $method->bank_name, ctrans('texts.ach'));
$payment_meta->last4 = (string) $method->last4;
$payment_meta->type = GatewayType::BANK_TRANSFER;
$data = [
'payment_meta' => $payment_meta,
'token' => $method->id,
'payment_method_id' => $payment_method_id,
];
return $this->stripe->storeGatewayToken($data, ['gateway_customer_reference' => $customer->id]);
} catch (\Exception $e) {
return $this->stripe->processInternallyFailedPayment($this->stripe, $e);
}
} }
} }

View File

@ -13,6 +13,8 @@
namespace App\PaymentDrivers\Stripe; namespace App\PaymentDrivers\Stripe;
use App\Events\Payment\PaymentWasCreated; use App\Events\Payment\PaymentWasCreated;
use App\Exceptions\PaymentFailed;
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
use App\Jobs\Mail\PaymentFailureMailer; use App\Jobs\Mail\PaymentFailureMailer;
use App\Jobs\Util\SystemLogger; use App\Jobs\Util\SystemLogger;
use App\Models\ClientGatewayToken; use App\Models\ClientGatewayToken;
@ -42,50 +44,22 @@ class CreditCard
{ {
$intent['intent'] = $this->stripe->getSetupIntent(); $intent['intent'] = $this->stripe->getSetupIntent();
return render('gateways.stripe.add_credit_card', array_merge($data, $intent)); return render('gateways.stripe.credit_card.authorize', array_merge($data, $intent));
} }
public function authorizeResponse($request) public function authorizeResponse($request)
{ {
$server_response = json_decode($request->input('gateway_response')); $this->stripe->init();
$gateway_id = $request->input('gateway_id'); $stripe_response = json_decode($request->input('gateway_response'));
$gateway_type_id = $request->input('payment_method_id');
$is_default = $request->input('is_default');
$payment_method = $server_response->payment_method;
$customer = $this->stripe->findOrCreateCustomer(); $customer = $this->stripe->findOrCreateCustomer();
$this->stripe->init(); $this->stripe->attach($stripe_response->payment_method, $customer);
$stripe_payment_method = PaymentMethod::retrieve($payment_method); $stripe_method = $this->stripe->getStripePaymentMethod($stripe_response->payment_method);
$stripe_payment_method_obj = $stripe_payment_method->jsonSerialize();
$stripe_payment_method->attach(['customer' => $customer->id]);
$payment_meta = new stdClass; $this->storePaymentMethod($stripe_method, $request->payment_method_id, $customer);
$payment_meta->exp_month = (string)$stripe_payment_method_obj['card']['exp_month'];
$payment_meta->exp_year = (string)$stripe_payment_method_obj['card']['exp_year'];
$payment_meta->brand = (string)$stripe_payment_method_obj['card']['brand'];
$payment_meta->last4 = (string)$stripe_payment_method_obj['card']['last4'];
$payment_meta->type = GatewayType::CREDIT_CARD;
$client_gateway_token = new ClientGatewayToken();
$client_gateway_token->company_id = $this->stripe->client->company->id;
$client_gateway_token->client_id = $this->stripe->client->id;
$client_gateway_token->token = $payment_method;
$client_gateway_token->company_gateway_id = $this->stripe->company_gateway->id;
$client_gateway_token->gateway_type_id = $gateway_type_id;
$client_gateway_token->gateway_customer_reference = $customer->id;
$client_gateway_token->meta = $payment_meta;
$client_gateway_token->save();
if ($is_default == 'true' || $this->stripe->client->gateway_tokens->count() == 1) {
$this->stripe->client->gateway_tokens()->update(['is_default' => 0]);
$client_gateway_token->is_default = 1;
$client_gateway_token->save();
}
return redirect()->route('client.payment_methods.index'); return redirect()->route('client.payment_methods.index');
} }
@ -96,7 +70,7 @@ class CreditCard
'amount' => $this->stripe->convertToStripeAmount($data['amount_with_fee'], $this->stripe->client->currency()->precision), 'amount' => $this->stripe->convertToStripeAmount($data['amount_with_fee'], $this->stripe->client->currency()->precision),
'currency' => $this->stripe->client->getCurrencyCode(), 'currency' => $this->stripe->client->getCurrencyCode(),
'customer' => $this->stripe->findOrCreateCustomer(), 'customer' => $this->stripe->findOrCreateCustomer(),
'description' => collect($data['invoices'])->pluck('id'), //todo more meaningful description here: 'description' => collect($data['invoices'])->pluck('id'), // TODO: More meaningful description.
]; ];
if ($data['token']) { if ($data['token']) {
@ -110,114 +84,66 @@ class CreditCard
$data['intent'] = $this->stripe->createPaymentIntent($payment_intent_data); $data['intent'] = $this->stripe->createPaymentIntent($payment_intent_data);
$data['gateway'] = $this->stripe; $data['gateway'] = $this->stripe;
return render('gateways.stripe.credit_card', $data); return render('gateways.stripe.credit_card.pay', $data);
} }
public function paymentResponse($request) public function paymentResponse(PaymentResponseRequest $request)
{ {
$server_response = json_decode($request->input('gateway_response'));
$payment_hash = PaymentHash::whereRaw('BINARY `hash`= ?', [$request->input('payment_hash')])->firstOrFail();
$state = [
'payment_method' => $server_response->payment_method,
'payment_status' => $server_response->status,
'save_card' => $request->store_card,
'gateway_type_id' => $request->payment_method_id,
'hashed_ids' => $request->hashed_ids,
'server_response' => $server_response,
'payment_hash' => $payment_hash,
];
/*Hydrate the invoices from the payment hash*/
$invoices = Invoice::whereIn('id', $this->stripe->transformKeys(array_column($payment_hash->invoices(), 'invoice_id')))
->whereClientId($this->stripe->client->id)
->get();
if ($this->stripe->getContact()) {
$client_contact = $this->stripe->getContact();
} else {
$client_contact = $invoices->first()->invitations->first()->contact;
}
$this->stripe->init(); $this->stripe->init();
$state['payment_intent'] = PaymentIntent::retrieve($server_response->id); $state = [
'server_response' => json_decode($request->gateway_response),
'payment_hash' => $request->payment_hash,
];
$state = array_merge($state, $request->all());
$state['store_card'] = boolval($state['store_card']);
$state['payment_intent'] = \Stripe\PaymentIntent::retrieve($state['server_response']->id);
$state['customer'] = $state['payment_intent']->customer; $state['customer'] = $state['payment_intent']->customer;
if ($state['payment_status'] == 'succeeded') { $this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, $state);
$this->stripe->payment_hash->save();
/* Add gateway fees if needed! */ $server_response = $this->stripe->payment_hash->data->server_response;
if ($server_response->status == 'succeeded') {
$this->stripe->confirmGatewayFee($request); $this->stripe->confirmGatewayFee($request);
return $this->processSuccessfulPayment($state); return $this->processSuccessfulPayment();
} }
return $this->processUnsuccessfulPayment($server_response); return $this->processUnsuccessfulPayment($server_response);
} }
private function processSuccessfulPayment($state) private function processSuccessfulPayment()
{ {
$state['charge_id'] = $state['payment_intent']->charges->data[0]->id; $stripe_method = $this->stripe->getStripePaymentMethod($this->stripe->payment_hash->data->server_response->payment_method);
$this->stripe->init(); if ($this->stripe->payment_hash->data->store_card) {
$customer = $this->stripe->findOrCreateCustomer();
$state['payment_method'] = PaymentMethod::retrieve($state['payment_method']); $this->stripe->attach($this->stripe->payment_hash->data->server_response->payment_method, $customer);
$payment_method_object = $state['payment_method']->jsonSerialize();
$state['payment_meta'] = [ $this->storePaymentMethod($stripe_method, $this->stripe->payment_hash->data->payment_method_id, $customer);
'exp_month' => (string)$payment_method_object['card']['exp_month'],
'exp_year' => (string)$payment_method_object['card']['exp_year'],
'brand' => (string)$payment_method_object['card']['brand'],
'last4' => (string)$payment_method_object['card']['last4'],
'type' => GatewayType::CREDIT_CARD,
];
$payment_meta = new stdClass;
$payment_meta->exp_month = (string)$payment_method_object['card']['exp_month'];
$payment_meta->exp_year = (string)$payment_method_object['card']['exp_year'];
$payment_meta->brand = (string)$payment_method_object['card']['brand'];
$payment_meta->last4 = (string)$payment_method_object['card']['last4'];
$payment_meta->type = GatewayType::CREDIT_CARD;
$payment_type = PaymentType::parseCardType($payment_method_object['card']['brand']);
if ($state['save_card'] == true || $state['save_card'] == 'true') {
$this->saveCard($state);
}
// Todo: Need to fix this to support payment types other than credit card.... sepa etc etc
if (! isset($state['payment_type'])) {
$state['payment_type'] = PaymentType::CREDIT_CARD_OTHER;
} }
$data = [ $data = [
'payment_method' => $state['charge_id'], 'payment_method' => $this->stripe->payment_hash->data->server_response->payment_method,
'payment_type' => $state['payment_type'], 'payment_type' => PaymentType::parseCardType(strtolower($stripe_method->card->brand)),
'amount' => $state['server_response']->amount, 'amount' => $this->stripe->convertFromStripeAmount($this->stripe->payment_hash->data->server_response->amount, $this->stripe->client->currency()->precision),
'gateway_type_id' => GatewayType::CREDIT_CARD, 'transaction_reference' => $this->stripe->payment_hash->data->server_response->id,
]; ];
$payment = $this->stripe->createPayment($data, $status = Payment::STATUS_COMPLETED); $payment = $this->stripe->createPayment($data, \App\Models\Payment::STATUS_COMPLETED);
$payment->meta = $payment_meta;
$payment->save();
$payment_hash = $state['payment_hash']; SystemLogger::dispatch(
$payment_hash->payment_id = $payment->id; ['response' => $this->stripe->payment_hash->data->server_response, 'data' => $data],
$payment_hash->save(); SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_SUCCESS,
$payment = $this->stripe->attachInvoices($payment, $state['payment_hash']); SystemLog::TYPE_STRIPE,
$this->stripe->client
$payment->service()->updateInvoicePayment($state['payment_hash']); );
event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars()));
$logger_message = [
'server_response' => $state['payment_intent'],
'data' => $data,
];
SystemLogger::dispatch($logger_message, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_STRIPE, $this->stripe->client);
return redirect()->route('client.payments.show', ['payment' => $this->stripe->encodePrimaryKey($payment->id)]); return redirect()->route('client.payments.show', ['payment' => $this->stripe->encodePrimaryKey($payment->id)]);
} }
@ -226,14 +152,49 @@ class CreditCard
{ {
PaymentFailureMailer::dispatch($this->stripe->client, $server_response->cancellation_reason, $this->stripe->client->company, $server_response->amount); PaymentFailureMailer::dispatch($this->stripe->client, $server_response->cancellation_reason, $this->stripe->client->company, $server_response->amount);
PaymentFailureMailer::dispatch(
$this->stripe->client,
$server_response,
$this->stripe->client->company,
$server_response->amount
);
$message = [ $message = [
'server_response' => $server_response, 'server_response' => $server_response,
'data' => [], 'data' => $this->stripe->payment_hash->data,
]; ];
SystemLogger::dispatch($message, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_STRIPE, $this->stripe->client); SystemLogger::dispatch(
$message,
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_FAILURE,
SystemLog::TYPE_STRIPE,
$this->stripe->client
);
throw new Exception('Failed to process the payment.', 1); throw new PaymentFailed('Failed to process the payment.', 500);
}
private function storePaymentMethod(\Stripe\PaymentMethod $method, $payment_method_id, $customer)
{
try {
$payment_meta = new \stdClass;
$payment_meta->exp_month = (string) $method->card->exp_month;
$payment_meta->exp_year = (string) $method->card->exp_year;
$payment_meta->brand = (string) $method->card->brand;
$payment_meta->last4 = (string) $method->card->last4;
$payment_meta->type = GatewayType::CREDIT_CARD;
$data = [
'payment_meta' => $payment_meta,
'token' => $method->id,
'payment_method_id' => $payment_method_id,
];
$this->stripe->storeGatewayToken($data, ['gateway_customer_reference' => $customer->id]);
} catch (\Exception $e) {
return $this->stripe->processInternallyFailedPayment($this->stripe, $e);
}
} }
private function saveCard($state) private function saveCard($state)

View File

@ -15,6 +15,7 @@ namespace App\PaymentDrivers;
use App\Events\Payment\PaymentWasCreated; use App\Events\Payment\PaymentWasCreated;
use App\Factory\PaymentFactory; use App\Factory\PaymentFactory;
use App\Http\Requests\Payments\PaymentWebhookRequest; use App\Http\Requests\Payments\PaymentWebhookRequest;
use App\Http\Requests\Request;
use App\Jobs\Mail\PaymentFailureMailer; use App\Jobs\Mail\PaymentFailureMailer;
use App\Jobs\Util\SystemLogger; use App\Jobs\Util\SystemLogger;
use App\Models\ClientGatewayToken; use App\Models\ClientGatewayToken;
@ -33,9 +34,6 @@ use App\PaymentDrivers\Stripe\CreditCard;
use App\PaymentDrivers\Stripe\SOFORT; use App\PaymentDrivers\Stripe\SOFORT;
use App\PaymentDrivers\Stripe\Utilities; use App\PaymentDrivers\Stripe\Utilities;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use Exception;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use Illuminate\View\View; use Illuminate\View\View;
use Stripe\Customer; use Stripe\Customer;
@ -54,36 +52,22 @@ class StripePaymentDriver extends BaseDriver
public $can_authorise_credit_card = true; public $can_authorise_credit_card = true;
/** @var StripeClient */ /** @var \Stripe\StripeClient */
protected $stripe; public $stripe;
protected $customer_reference = 'customerReferenceParam'; protected $customer_reference = 'customerReferenceParam';
public $payment_method; public $payment_method;
public static $methods = [ public static $methods = [
GatewayType::CREDIT_CARD => CreditCard::class, GatewayType::CREDIT_CARD => CreditCard::class,
GatewayType::BANK_TRANSFER => ACH::class, GatewayType::BANK_TRANSFER => ACH::class,
GatewayType::ALIPAY => Alipay::class, GatewayType::ALIPAY => Alipay::class,
GatewayType::SOFORT => SOFORT::class, GatewayType::SOFORT => SOFORT::class,
GatewayType::APPLE_PAY => 1, GatewayType::APPLE_PAY => 1, // TODO
GatewayType::SEPA => 1, GatewayType::SEPA => 1, // TODO
]; ];
/**
* Methods in this class are divided into
* two separate streams.
*
* 1. Omnipay Specific
* 2. Stripe Specific
*
* Our Stripe integration is deeper than
* other gateways and therefore
* relies on direct calls to the API
*/
/************************************** Stripe API methods **********************************************************/
/** /**
* Initializes the Stripe API. * Initializes the Stripe API.
* @return void * @return void
@ -237,23 +221,6 @@ class StripePaymentDriver extends BaseDriver
return $this->payment_method->paymentResponse($request); return $this->payment_method->paymentResponse($request);
} }
public function createPayment($data, $status = Payment::STATUS_COMPLETED): Payment
{
$payment = parent::createPayment($data, $status);
$client_contact = $this->getContact();
$client_contact_id = $client_contact ? $client_contact->id : null;
$payment->amount = $this->convertFromStripeAmount($data['amount'], $this->client->currency()->precision);
$payment->type_id = $data['payment_type'];
$payment->transaction_reference = $data['payment_method'];
$payment->client_contact_id = $client_contact_id;
$payment->gateway_type_id = GatewayType::ALIPAY;
$payment->save();
return $payment;
}
/** /**
* Creates a new String Payment Intent. * Creates a new String Payment Intent.
* *
@ -368,9 +335,9 @@ class StripePaymentDriver extends BaseDriver
return $this->payment_method->verificationView($payment_method); return $this->payment_method->verificationView($payment_method);
} }
public function processVerification(ClientGatewayToken $payment_method) public function processVerification(Request $request, ClientGatewayToken $payment_method)
{ {
return $this->payment_method->processVerification($payment_method); return $this->payment_method->processVerification($request, $payment_method);
} }
public function processWebhookRequest(PaymentWebhookRequest $request, Company $company, CompanyGateway $company_gateway, Payment $payment) public function processWebhookRequest(PaymentWebhookRequest $request, Company $company, CompanyGateway $company_gateway, Payment $payment)
@ -413,6 +380,25 @@ class StripePaymentDriver extends BaseDriver
return $payment->service()->applyNumber()->save(); return $payment->service()->applyNumber()->save();
} }
/**
* Attach Stripe payment method to Stripe client.
*
* @param string $payment_method
* @param mixed $customer
*
* @return void
*/
public function attach(string $payment_method, $customer): void
{
try {
$stripe_payment_method = $this->getStripePaymentMethod($payment_method);
$stripe_payment_method->attach(['customer' => $customer->id]);
}
catch(\Stripe\Exception\ApiErrorException | \Exception $e) {
$this->processInternallyFailedPayment($this, $e);
}
}
/** /**
* Detach payment method from the Stripe. * Detach payment method from the Stripe.
* https://stripe.com/docs/api/payment_methods/detach * https://stripe.com/docs/api/payment_methods/detach
@ -430,15 +416,29 @@ class StripePaymentDriver extends BaseDriver
$response = $stripe->paymentMethods->detach($token->token); $response = $stripe->paymentMethods->detach($token->token);
} catch (Exception $e) { } catch (Exception $e) {
SystemLogger::dispatch([ SystemLogger::dispatch([
'server_response' => $response, 'data' => request()->all(), 'server_response' => $e->getMessage(), 'data' => request()->all(),
], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_STRIPE, $this->client); ], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_STRIPE, $this->client);
} }
} }
public function getCompanyGatewayId(): int public function getCompanyGatewayId(): int
{ {
return $this->company_gateway->id; return $this->company_gateway->id;
} }
/**
* Retrieve payment method from Stripe.
*
* @param string $source
*
* @return \Stripe\PaymentMethod|void
*/
public function getStripePaymentMethod(string $source)
{
try {
return \Stripe\PaymentMethod::retrieve($source);
} catch (\Stripe\Exception\ApiErrorException | \Exception $e) {
return $this->processInternallyFailedPayment($this, $e);
}
}
} }

2
public/css/app.css vendored

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
/*! For license information please see action-selectors.js.LICENSE.txt */ /*! For license information please see action-selectors.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=5)}({5:function(e,t,n){e.exports=n("Boob")},Boob:function(e,t){function n(e,t){var n;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(n=function(e,t){if(!e)return;if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return r(e,t)}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var o=0,c=function(){};return{s:c,n:function(){return o>=e.length?{done:!0}:{done:!1,value:e[o++]}},e:function(e){throw e},f:c}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var u,i=!0,l=!1;return{s:function(){n=e[Symbol.iterator]()},n:function(){var e=n.next();return i=e.done,e},e:function(e){l=!0,u=e},f:function(){try{i||null==n.return||n.return()}finally{if(l)throw u}}}}function r(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function o(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}(new(function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.parentElement=document.querySelector(".form-check-parent"),this.parentForm=document.getElementById("bulkActions")}var t,r,c;return t=e,(r=[{key:"watchCheckboxes",value:function(e){var t=this;document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})),document.querySelectorAll(".form-check-child").forEach((function(n){e.checked?(n.checked=e.checked,t.processChildItem(n,document.getElementById("bulkActions"))):(n.checked=!1,document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})))}))}},{key:"processChildItem",value:function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(r.hasOwnProperty("single")&&document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})),!1!==e.checked){var o=document.createElement("INPUT");o.setAttribute("name","invoices[]"),o.setAttribute("value",e.dataset.value),o.setAttribute("class","child-hidden-input"),o.hidden=!0,t.append(o)}else{var c,u=document.querySelectorAll("input.child-hidden-input"),i=n(u);try{for(i.s();!(c=i.n()).done;){var l=c.value;l.value==e.dataset.value&&l.remove()}}catch(e){i.e(e)}finally{i.f()}}}},{key:"handle",value:function(){var e=this;this.parentElement.addEventListener("click",(function(){e.watchCheckboxes(e.parentElement)}));var t,r=n(document.querySelectorAll(".form-check-child"));try{var o=function(){var n=t.value;n.addEventListener("click",(function(){e.processChildItem(n,e.parentForm)}))};for(r.s();!(t=r.n()).done;)o()}catch(e){r.e(e)}finally{r.f()}}}])&&o(t.prototype,r),c&&o(t,c),e}())).handle()}}); !function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=4)}({4:function(e,t,n){e.exports=n("Boob")},Boob:function(e,t){function n(e,t){var n;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(n=function(e,t){if(!e)return;if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return r(e,t)}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var o=0,c=function(){};return{s:c,n:function(){return o>=e.length?{done:!0}:{done:!1,value:e[o++]}},e:function(e){throw e},f:c}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var u,i=!0,l=!1;return{s:function(){n=e[Symbol.iterator]()},n:function(){var e=n.next();return i=e.done,e},e:function(e){l=!0,u=e},f:function(){try{i||null==n.return||n.return()}finally{if(l)throw u}}}}function r(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function o(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}(new(function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.parentElement=document.querySelector(".form-check-parent"),this.parentForm=document.getElementById("bulkActions")}var t,r,c;return t=e,(r=[{key:"watchCheckboxes",value:function(e){var t=this;document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})),document.querySelectorAll(".form-check-child").forEach((function(n){e.checked?(n.checked=e.checked,t.processChildItem(n,document.getElementById("bulkActions"))):(n.checked=!1,document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})))}))}},{key:"processChildItem",value:function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(r.hasOwnProperty("single")&&document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})),!1!==e.checked){var o=document.createElement("INPUT");o.setAttribute("name","invoices[]"),o.setAttribute("value",e.dataset.value),o.setAttribute("class","child-hidden-input"),o.hidden=!0,t.append(o)}else{var c,u=document.querySelectorAll("input.child-hidden-input"),i=n(u);try{for(i.s();!(c=i.n()).done;){var l=c.value;l.value==e.dataset.value&&l.remove()}}catch(e){i.e(e)}finally{i.f()}}}},{key:"handle",value:function(){var e=this;this.parentElement.addEventListener("click",(function(){e.watchCheckboxes(e.parentElement)}));var t,r=n(document.querySelectorAll(".form-check-child"));try{var o=function(){var n=t.value;n.addEventListener("click",(function(){e.processChildItem(n,e.parentForm)}))};for(r.s();!(t=r.n()).done;)o()}catch(e){r.e(e)}finally{r.f()}}}])&&o(t.prototype,r),c&&o(t,c),e}())).handle()}});

View File

@ -1,2 +1,2 @@
/*! For license information please see payment.js.LICENSE.txt */ /*! For license information please see payment.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=6)}({6:function(e,t,n){e.exports=n("FuOr")},FuOr:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var r=function(){function e(t,n){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.shouldDisplayTerms=t,this.shouldDisplaySignature=n,this.termsAccepted=!1}var t,r,i;return t=e,(r=[{key:"handleMethodSelect",value:function(e){var t=this;document.getElementById("company_gateway_id").value=e.dataset.companyGatewayId,document.getElementById("payment_method_id").value=e.dataset.gatewayTypeId,this.shouldDisplaySignature&&!this.shouldDisplayTerms&&(this.displayTerms(),document.getElementById("accept-terms-button").addEventListener("click",(function(){t.termsAccepted=!0,t.submitForm()}))),!this.shouldDisplaySignature&&this.shouldDisplayTerms&&(this.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){document.querySelector('input[name="signature"').value=t.signaturePad.toDataURL(),t.submitForm()}))),this.shouldDisplaySignature&&this.shouldDisplayTerms&&(this.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){t.displayTerms(),document.getElementById("accept-terms-button").addEventListener("click",(function(){document.querySelector('input[name="signature"').value=t.signaturePad.toDataURL(),t.termsAccepted=!0,t.submitForm()}))}))),this.shouldDisplaySignature||this.shouldDisplayTerms||this.submitForm()}},{key:"submitForm",value:function(){document.getElementById("payment-form").submit()}},{key:"displayTerms",value:function(){document.getElementById("displayTermsModal").removeAttribute("style")}},{key:"displaySignature",value:function(){document.getElementById("displaySignatureModal").removeAttribute("style");var e=new SignaturePad(document.getElementById("signature-pad"),{penColor:"rgb(0, 0, 0)"});this.signaturePad=e}},{key:"handle",value:function(){var e=this;document.querySelectorAll(".dropdown-gateway-button").forEach((function(t){t.addEventListener("click",(function(){return e.handleMethodSelect(t)}))}))}}])&&n(t.prototype,r),i&&n(t,i),e}(),i=document.querySelector('meta[name="require-invoice-signature"]').content,u=document.querySelector('meta[name="show-invoice-terms"]').content;new r(Boolean(+i),Boolean(+u)).handle()}}); !function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=5)}({5:function(e,t,n){e.exports=n("FuOr")},FuOr:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var r=function(){function e(t,n){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.shouldDisplayTerms=t,this.shouldDisplaySignature=n,this.termsAccepted=!1}var t,r,i;return t=e,(r=[{key:"handleMethodSelect",value:function(e){var t=this;document.getElementById("company_gateway_id").value=e.dataset.companyGatewayId,document.getElementById("payment_method_id").value=e.dataset.gatewayTypeId,this.shouldDisplaySignature&&!this.shouldDisplayTerms&&(this.displayTerms(),document.getElementById("accept-terms-button").addEventListener("click",(function(){t.termsAccepted=!0,t.submitForm()}))),!this.shouldDisplaySignature&&this.shouldDisplayTerms&&(this.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){document.querySelector('input[name="signature"').value=t.signaturePad.toDataURL(),t.submitForm()}))),this.shouldDisplaySignature&&this.shouldDisplayTerms&&(this.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){t.displayTerms(),document.getElementById("accept-terms-button").addEventListener("click",(function(){document.querySelector('input[name="signature"').value=t.signaturePad.toDataURL(),t.termsAccepted=!0,t.submitForm()}))}))),this.shouldDisplaySignature||this.shouldDisplayTerms||this.submitForm()}},{key:"submitForm",value:function(){document.getElementById("payment-form").submit()}},{key:"displayTerms",value:function(){document.getElementById("displayTermsModal").removeAttribute("style")}},{key:"displaySignature",value:function(){document.getElementById("displaySignatureModal").removeAttribute("style");var e=new SignaturePad(document.getElementById("signature-pad"),{penColor:"rgb(0, 0, 0)"});this.signaturePad=e}},{key:"handle",value:function(){var e=this;document.querySelectorAll(".dropdown-gateway-button").forEach((function(t){t.addEventListener("click",(function(){return e.handleMethodSelect(t)}))}))}}])&&n(t.prototype,r),i&&n(t,i),e}(),i=document.querySelector('meta[name="require-invoice-signature"]').content,u=document.querySelector('meta[name="show-invoice-terms"]').content;new r(Boolean(+i),Boolean(+u)).handle()}});

View File

@ -1,2 +1,112 @@
/*! For license information please see authorize-ach.js.LICENSE.txt */ /******/ (function(modules) { // webpackBootstrap
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=4)}({4:function(e,t,n){e.exports=n("UWWK")},UWWK:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}(new(function(){function e(){var t=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),r(this,"setupStripe",(function(){return t.stripe=Stripe(t.key),t})),r(this,"getFormData",(function(){return{country:document.getElementById("country").value,currency:document.getElementById("currency").value,routing_number:document.getElementById("routing-number").value,account_number:document.getElementById("account-number").value,account_holder_name:document.getElementById("account-holder-name").value,account_holder_type:document.querySelector('input[name="account-holder-type"]:checked').value}})),r(this,"handleError",(function(e){document.getElementById("save-button").disabled=!1,document.querySelector("#save-button > svg").classList.add("hidden"),document.querySelector("#save-button > span").classList.remove("hidden"),t.errors.textContent="",t.errors.textContent=e,t.errors.hidden=!1})),r(this,"handleSuccess",(function(e){document.getElementById("gateway_response").value=JSON.stringify(e),document.getElementById("server_response").submit()})),r(this,"handleSubmit",(function(e){document.getElementById("save-button").disabled=!0,document.querySelector("#save-button > svg").classList.remove("hidden"),document.querySelector("#save-button > span").classList.add("hidden"),e.preventDefault(),t.errors.textContent="",t.errors.hidden=!0,t.stripe.createToken("bank_account",t.getFormData()).then((function(e){return e.hasOwnProperty("error")?t.handleError(e.error.message):t.handleSuccess(e)}))})),this.errors=document.getElementById("errors"),this.key=document.querySelector('meta[name="stripe-publishable-key"]').content}var t,o,u;return t=e,(o=[{key:"handle",value:function(){var e=this;document.getElementById("token-form").addEventListener("submit",(function(t){return e.handleSubmit(t)}))}}])&&n(t.prototype,o),u&&n(t,u),e}())).setupStripe().handle()}}); /******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "/";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 3);
/******/ })
/************************************************************************/
/******/ ({
/***/ "./resources/js/clients/payment_methods/authorize-ach.js":
/*!***************************************************************!*\
!*** ./resources/js/clients/payment_methods/authorize-ach.js ***!
\***************************************************************/
/*! no static exports found */
/***/ (function(module, exports) {
throw new Error("Module build failed (from ./node_modules/babel-loader/lib/index.js):\nError: ENOENT: no such file or directory, open '/home/benjamin/Development/invoiceninja/resources/js/clients/payment_methods/authorize-ach.js'");
/***/ }),
/***/ 3:
/*!*********************************************************************!*\
!*** multi ./resources/js/clients/payment_methods/authorize-ach.js ***!
\*********************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(/*! /home/benjamin/Development/invoiceninja/resources/js/clients/payment_methods/authorize-ach.js */"./resources/js/clients/payment_methods/authorize-ach.js");
/***/ })
/******/ });

View File

@ -1,2 +1,2 @@
/*! For license information please see authorize-authorize-card.js.LICENSE.txt */ /*! For license information please see authorize-authorize-card.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var a=t[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,n),a.l=!0,a.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)n.d(r,a,function(t){return e[t]}.bind(null,a));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=2)}({2:function(e,t,n){e.exports=n("6vDv")},"6vDv":function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}new(function(){function e(t,n){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.publicKey=t,this.loginId=n,this.cardHolderName=document.getElementById("cardholder_name"),this.cardButton=document.getElementById("card_button")}var t,r,a;return t=e,(r=[{key:"handleAuthorization",value:function(){var e=$("#my-card"),t={};t.clientKey=this.publicKey,t.apiLoginID=this.loginId;var n={};n.cardNumber=e.CardJs("cardNumber"),n.month=e.CardJs("expiryMonth"),n.year=e.CardJs("expiryYear"),n.cardCode=document.getElementById("cvv").value;var r={};return r.authData=t,r.cardData=n,document.getElementById("card_button").disabled=!0,document.querySelector("#card_button > svg").classList.remove("hidden"),document.querySelector("#card_button > span").classList.add("hidden"),Accept.dispatchData(r,this.responseHandler),!1}},{key:"responseHandler",value:function(e){if("Error"===e.messages.resultCode){for(var t=0;t<e.messages.message.length;)console.log(e.messages.message[t].code+": "+e.messages.message[t].text),t+=1;document.getElementById("card_button").disabled=!1,document.querySelector("#card_button > svg").classList.add("hidden"),document.querySelector("#card_button > span").classList.remove("hidden")}else"Ok"===e.messages.resultCode&&(document.getElementById("dataDescriptor").value=e.opaqueData.dataDescriptor,document.getElementById("dataValue").value=e.opaqueData.dataValue,document.getElementById("server_response").submit());return!1}},{key:"handle",value:function(){var e=this;return this.cardButton.addEventListener("click",(function(){e.cardButton.disabled=!e.cardButton.disabled,e.handleAuthorization()})),this}}])&&n(t.prototype,r),a&&n(t,a),e}())(document.querySelector('meta[name="authorize-public-key"]').content,document.querySelector('meta[name="authorize-login-id"]').content).handle()}}); !function(e){var t={};function n(r){if(t[r])return t[r].exports;var a=t[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,n),a.l=!0,a.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)n.d(r,a,function(t){return e[t]}.bind(null,a));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=1)}({1:function(e,t,n){e.exports=n("6vDv")},"6vDv":function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}new(function(){function e(t,n){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.publicKey=t,this.loginId=n,this.cardHolderName=document.getElementById("cardholder_name"),this.cardButton=document.getElementById("card_button")}var t,r,a;return t=e,(r=[{key:"handleAuthorization",value:function(){var e=$("#my-card"),t={};t.clientKey=this.publicKey,t.apiLoginID=this.loginId;var n={};n.cardNumber=e.CardJs("cardNumber"),n.month=e.CardJs("expiryMonth"),n.year=e.CardJs("expiryYear"),n.cardCode=document.getElementById("cvv").value;var r={};return r.authData=t,r.cardData=n,document.getElementById("card_button").disabled=!0,document.querySelector("#card_button > svg").classList.remove("hidden"),document.querySelector("#card_button > span").classList.add("hidden"),Accept.dispatchData(r,this.responseHandler),!1}},{key:"responseHandler",value:function(e){if("Error"===e.messages.resultCode){for(var t=0;t<e.messages.message.length;)console.log(e.messages.message[t].code+": "+e.messages.message[t].text),t+=1;document.getElementById("card_button").disabled=!1,document.querySelector("#card_button > svg").classList.add("hidden"),document.querySelector("#card_button > span").classList.remove("hidden")}else"Ok"===e.messages.resultCode&&(document.getElementById("dataDescriptor").value=e.opaqueData.dataDescriptor,document.getElementById("dataValue").value=e.opaqueData.dataValue,document.getElementById("server_response").submit());return!1}},{key:"handle",value:function(){var e=this;return this.cardButton.addEventListener("click",(function(){e.cardButton.disabled=!e.cardButton.disabled,e.handleAuthorization()})),this}}])&&n(t.prototype,r),a&&n(t,a),e}())(document.querySelector('meta[name="authorize-public-key"]').content,document.querySelector('meta[name="authorize-login-id"]').content).handle()}});

View File

@ -1,2 +1,215 @@
/*! For license information please see authorize-stripe-card.js.LICENSE.txt */ /******/ (function(modules) { // webpackBootstrap
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var a=t[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,n),a.l=!0,a.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)n.d(r,a,function(t){return e[t]}.bind(null,a));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=1)}({1:function(e,t,n){e.exports=n("jzun")},jzun:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}new(function(){function e(t){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.key=t,this.cardHolderName=document.getElementById("cardholder-name"),this.cardButton=document.getElementById("card-button"),this.clientSecret=this.cardButton.dataset.secret}var t,r,a;return t=e,(r=[{key:"setupStripe",value:function(){return this.stripe=Stripe(this.key),this.elements=this.stripe.elements(),this}},{key:"createElement",value:function(){return this.cardElement=this.elements.create("card"),this}},{key:"mountCardElement",value:function(){return this.cardElement.mount("#card-element"),this}},{key:"handleStripe",value:function(e,t){var n=this;this.cardButton.disabled=!0,this.cardButton.querySelector("span").classList.add("hidden"),this.cardButton.querySelector("svg").classList.remove("hidden"),e.handleCardSetup(this.clientSecret,this.cardElement,{payment_method_data:{billing_details:{name:t.value}}}).then((function(e){return e.error?n.handleFailure(e):n.handleSuccess(e)}))}},{key:"handleFailure",value:function(e){this.cardButton.disabled=!1,this.cardButton.querySelector("span").classList.remove("hidden"),this.cardButton.querySelector("svg").classList.add("hidden");var t=document.getElementById("errors");t.textContent="",t.textContent=e.error.message,t.hidden=!1}},{key:"handleSuccess",value:function(e){document.getElementById("gateway_response").value=JSON.stringify(e.setupIntent),document.getElementById("is_default").value=document.getElementById("proxy_is_default").checked,document.getElementById("server_response").submit()}},{key:"handle",value:function(){var e=this;return this.setupStripe().createElement().mountCardElement(),this.cardButton.addEventListener("click",(function(){e.handleStripe(e.stripe,e.cardHolderName)})),this}}])&&n(t.prototype,r),a&&n(t,a),e}())(document.querySelector('meta[name="stripe-publishable-key"]').content).handle()}}); /******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "/";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 1);
/******/ })
/************************************************************************/
/******/ ({
/***/ "./resources/js/clients/payment_methods/authorize-stripe-card.js":
/*!***********************************************************************!*\
!*** ./resources/js/clients/payment_methods/authorize-stripe-card.js ***!
\***********************************************************************/
/*! no static exports found */
/***/ (function(module, exports) {
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
var AuthorizeStripeCard = /*#__PURE__*/function () {
function AuthorizeStripeCard(key) {
_classCallCheck(this, AuthorizeStripeCard);
this.key = key;
this.cardHolderName = document.getElementById('cardholder-name');
this.cardButton = document.getElementById('card-button');
this.clientSecret = this.cardButton.dataset.secret;
}
_createClass(AuthorizeStripeCard, [{
key: "setupStripe",
value: function setupStripe() {
this.stripe = Stripe(this.key);
this.elements = this.stripe.elements();
return this;
}
}, {
key: "createElement",
value: function createElement() {
this.cardElement = this.elements.create('card');
return this;
}
}, {
key: "mountCardElement",
value: function mountCardElement() {
this.cardElement.mount('#card-element');
return this;
}
}, {
key: "handleStripe",
value: function handleStripe(stripe, cardHolderName) {
var _this = this;
this.cardButton.disabled = true;
this.cardButton.querySelector('span').classList.add('hidden');
this.cardButton.querySelector('svg').classList.remove('hidden');
stripe.handleCardSetup(this.clientSecret, this.cardElement, {
payment_method_data: {
billing_details: {
name: cardHolderName.value
}
}
}).then(function (result) {
if (result.error) {
return _this.handleFailure(result);
}
return _this.handleSuccess(result);
});
}
}, {
key: "handleFailure",
value: function handleFailure(result) {
this.cardButton.disabled = false;
this.cardButton.querySelector('span').classList.remove('hidden');
this.cardButton.querySelector('svg').classList.add('hidden');
var errors = document.getElementById('errors');
errors.textContent = '';
errors.textContent = result.error.message;
errors.hidden = false;
}
}, {
key: "handleSuccess",
value: function handleSuccess(result) {
document.getElementById('gateway_response').value = JSON.stringify(result.setupIntent);
document.getElementById('is_default').value = document.getElementById('proxy_is_default').checked;
document.getElementById('server_response').submit();
}
}, {
key: "handle",
value: function handle() {
var _this2 = this;
this.setupStripe().createElement().mountCardElement();
this.cardButton.addEventListener('click', function () {
_this2.handleStripe(_this2.stripe, _this2.cardHolderName);
});
return this;
}
}]);
return AuthorizeStripeCard;
}();
var publishableKey = document.querySelector('meta[name="stripe-publishable-key"]').content;
/** @handle */
new AuthorizeStripeCard(publishableKey).handle();
/***/ }),
/***/ 1:
/*!*****************************************************************************!*\
!*** multi ./resources/js/clients/payment_methods/authorize-stripe-card.js ***!
\*****************************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(/*! /home/benjamin/Development/invoiceninja/resources/js/clients/payment_methods/authorize-stripe-card.js */"./resources/js/clients/payment_methods/authorize-stripe-card.js");
/***/ })
/******/ });

View File

@ -0,0 +1,101 @@
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "/";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 3);
/******/ })
/************************************************************************/
/******/ ({
/***/ 3:
/*!******************************************************************!*\
!*** multi ./resources/js/clients/payment_methods/stripe-ach.js ***!
\******************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
!(function webpackMissingModule() { var e = new Error("Cannot find module '/home/benjamin/Development/invoiceninja/resources/js/clients/payment_methods/stripe-ach.js'"); e.code = 'MODULE_NOT_FOUND'; throw e; }());
/***/ })
/******/ });

View File

@ -1,2 +1,112 @@
/*! For license information please see alipay.js.LICENSE.txt */ /******/ (function(modules) { // webpackBootstrap
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=8)}({8:function(e,t,n){e.exports=n("HToU")},HToU:function(e,t){function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}new function e(t){var r=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),n(this,"setupStripe",(function(){return r.stripe=Stripe(r.key),r})),n(this,"handle",(function(){var e={type:"alipay",amount:document.querySelector('meta[name="amount"]').content,currency:document.querySelector('meta[name="currency"]').content,redirect:{return_url:document.querySelector('meta[name="return-url"]').content}};document.getElementById("pay-now").addEventListener("submit",(function(t){t.preventDefault(),document.getElementById("pay-now-button").disabled=!0,document.querySelector("#pay-now-button > svg").classList.add("hidden"),document.querySelector("#pay-now-button > span").classList.remove("hidden"),r.stripe.createSource(e).then((function(e){if(e.hasOwnProperty("source"))return window.location=e.source.redirect.url;document.getElementById("pay-now-button").disabled=!1,document.querySelector("#pay-now-button > svg").classList.remove("hidden"),document.querySelector("#pay-now-button > span").classList.add("hidden"),this.errors.textContent="",this.errors.textContent=e.error.message,this.errors.hidden=!1}))}))})),this.key=t,this.errors=document.getElementById("errors")}(document.querySelector('meta[name="stripe-publishable-key"]').content).setupStripe().handle()}}); /******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "/";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 7);
/******/ })
/************************************************************************/
/******/ ({
/***/ "./resources/js/clients/payments/alipay.js":
/*!*************************************************!*\
!*** ./resources/js/clients/payments/alipay.js ***!
\*************************************************/
/*! no static exports found */
/***/ (function(module, exports) {
throw new Error("Module build failed (from ./node_modules/babel-loader/lib/index.js):\nError: ENOENT: no such file or directory, open '/home/benjamin/Development/invoiceninja/resources/js/clients/payments/alipay.js'");
/***/ }),
/***/ 7:
/*!*******************************************************!*\
!*** multi ./resources/js/clients/payments/alipay.js ***!
\*******************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(/*! /home/benjamin/Development/invoiceninja/resources/js/clients/payments/alipay.js */"./resources/js/clients/payments/alipay.js");
/***/ })
/******/ });

View File

@ -1,2 +1,2 @@
/*! For license information please see authorize-credit-card-payment.js.LICENSE.txt */ /*! For license information please see authorize-credit-card-payment.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=3)}({3:function(e,t,n){e.exports=n("hK5p")},hK5p:function(e,t){function n(e,t){var n;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(n=function(e,t){if(!e)return;if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return r(e,t)}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var o=0,a=function(){};return{s:a,n:function(){return o>=e.length?{done:!0}:{done:!1,value:e[o++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var u,c=!0,i=!1;return{s:function(){n=e[Symbol.iterator]()},n:function(){var e=n.next();return c=e.done,e},e:function(e){i=!0,u=e},f:function(){try{c||null==n.return||n.return()}finally{if(i)throw u}}}}function r(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function o(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}new(function(){function e(t,r){var o=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),a(this,"handleAuthorization",(function(){var e=$("#my-card"),t={};t.clientKey=o.publicKey,t.apiLoginID=o.loginId;var n={};n.cardNumber=e.CardJs("cardNumber"),n.month=e.CardJs("expiryMonth"),n.year=e.CardJs("expiryYear"),n.cardCode=document.getElementById("cvv").value;var r={};return r.authData=t,r.cardData=n,document.getElementById("card_button").disabled=!0,document.querySelector("#card_button > svg").classList.remove("hidden"),document.querySelector("#card_button > span").classList.add("hidden"),Accept.dispatchData(r,o.responseHandler),!1})),a(this,"responseHandler",(function(e){if("Error"===e.messages.resultCode){$("#errors").show().html("<p>"+e.messages.message[0].code+": "+e.messages.message[0].text+"</p>"),document.getElementById("card_button").disabled=!1,document.querySelector("#card_button > svg").classList.add("hidden"),document.querySelector("#card_button > span").classList.remove("hidden")}else"Ok"===e.messages.resultCode&&(document.getElementById("dataDescriptor").value=e.opaqueData.dataDescriptor,document.getElementById("dataValue").value=e.opaqueData.dataValue,document.getElementById("store_card").value=document.getElementById("store_card_checkbox").checked,document.getElementById("server_response").submit());return!1})),a(this,"handle",(function(){if(o.cardButton&&o.cardButton.addEventListener("click",(function(){o.cardButton.disabled=!0,o.handleAuthorization()})),o.payNowButton){var e,t=n(o.payNowButton);try{var r=function(){var t=e.value;t.addEventListener("click",(function(){t.disabled=!0,o.handlePayNowAction(t.dataset.id)}))};for(t.s();!(e=t.n()).done;)r()}catch(e){t.e(e)}finally{t.f()}}return o})),this.publicKey=t,this.loginId=r,this.cardHolderName=document.getElementById("cardholder_name"),this.cardButton=document.getElementById("card_button"),this.payNowButton=document.getElementsByClassName("pay_now_button")}var t,r,u;return t=e,(r=[{key:"handlePayNowAction",value:function(e){document.getElementById("token").value=e,document.getElementById("server_response").submit()}}])&&o(t.prototype,r),u&&o(t,u),e}())(document.querySelector('meta[name="authorize-public-key"]').content,document.querySelector('meta[name="authorize-login-id"]').content).handle()}}); !function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=2)}({2:function(e,t,n){e.exports=n("hK5p")},hK5p:function(e,t){function n(e,t){var n;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(n=function(e,t){if(!e)return;if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return r(e,t)}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var o=0,a=function(){};return{s:a,n:function(){return o>=e.length?{done:!0}:{done:!1,value:e[o++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var u,c=!0,i=!1;return{s:function(){n=e[Symbol.iterator]()},n:function(){var e=n.next();return c=e.done,e},e:function(e){i=!0,u=e},f:function(){try{c||null==n.return||n.return()}finally{if(i)throw u}}}}function r(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function o(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}new(function(){function e(t,r){var o=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),a(this,"handleAuthorization",(function(){var e=$("#my-card"),t={};t.clientKey=o.publicKey,t.apiLoginID=o.loginId;var n={};n.cardNumber=e.CardJs("cardNumber"),n.month=e.CardJs("expiryMonth"),n.year=e.CardJs("expiryYear"),n.cardCode=document.getElementById("cvv").value;var r={};return r.authData=t,r.cardData=n,document.getElementById("card_button").disabled=!0,document.querySelector("#card_button > svg").classList.remove("hidden"),document.querySelector("#card_button > span").classList.add("hidden"),Accept.dispatchData(r,o.responseHandler),!1})),a(this,"responseHandler",(function(e){if("Error"===e.messages.resultCode){$("#errors").show().html("<p>"+e.messages.message[0].code+": "+e.messages.message[0].text+"</p>"),document.getElementById("card_button").disabled=!1,document.querySelector("#card_button > svg").classList.add("hidden"),document.querySelector("#card_button > span").classList.remove("hidden")}else"Ok"===e.messages.resultCode&&(document.getElementById("dataDescriptor").value=e.opaqueData.dataDescriptor,document.getElementById("dataValue").value=e.opaqueData.dataValue,document.getElementById("store_card").value=document.getElementById("store_card_checkbox").checked,document.getElementById("server_response").submit());return!1})),a(this,"handle",(function(){if(o.cardButton&&o.cardButton.addEventListener("click",(function(){o.cardButton.disabled=!0,o.handleAuthorization()})),o.payNowButton){var e,t=n(o.payNowButton);try{var r=function(){var t=e.value;t.addEventListener("click",(function(){t.disabled=!0,o.handlePayNowAction(t.dataset.id)}))};for(t.s();!(e=t.n()).done;)r()}catch(e){t.e(e)}finally{t.f()}}return o})),this.publicKey=t,this.loginId=r,this.cardHolderName=document.getElementById("cardholder_name"),this.cardButton=document.getElementById("card_button"),this.payNowButton=document.getElementsByClassName("pay_now_button")}var t,r,u;return t=e,(r=[{key:"handlePayNowAction",value:function(e){document.getElementById("token").value=e,document.getElementById("server_response").submit()}}])&&o(t.prototype,r),u&&o(t,u),e}())(document.querySelector('meta[name="authorize-public-key"]').content,document.querySelector('meta[name="authorize-login-id"]').content).handle()}});

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
/*! For license information please see checkout.com.js.LICENSE.txt */ /*! For license information please see checkout.com.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=9)}({9:function(e,t,n){e.exports=n("XYrq")},XYrq:function(e,t){window.CKOConfig={publicKey:document.querySelector('meta[name="public-key"]').content,customerEmail:document.querySelector('meta[name="customer-email"]').content,value:document.querySelector('meta[name="value"]').content,currency:document.querySelector('meta[name="currency"]').content,paymentMode:"cards",cardFormMode:"cardTokenisation",cardTokenised:function(e){document.querySelector('input[name="gateway_response"]').value=JSON.stringify(e.data),document.querySelector('input[name="store_card"]').value=document.querySelector("input[name=token-billing-checkbox]:checked").value,document.getElementById("server-response").submit()}}}}); !function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=8)}({8:function(e,t,n){e.exports=n("XYrq")},XYrq:function(e,t){document.getElementById("toggle-payment-with-token").addEventListener("click",(function(){document.getElementById("save-card--container").style.display="none",document.getElementById("checkout--container").style.display="none",document.getElementById("pay-now-with-token--container").style.display="block",document.querySelector("input[name=pay_with_token]").value=!0})),document.getElementById("toggle-payment-with-credit-card").addEventListener("click",(function(){document.getElementById("save-card--container").style.display="grid",document.getElementById("checkout--container").style.display="block",document.getElementById("pay-now-with-token--container").style.display="none",document.querySelector("input[name=pay_with_token]").value=!1}));var n=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;e&&(document.querySelector('input[name="gateway_response"]').value=JSON.stringify(e.data)),document.querySelector('input[name="store_card"]').value=document.querySelector("input[name=token-billing-checkbox]:checked").value,document.getElementById("server-response").submit()};document.getElementById("pay-now-with-token").addEventListener("click",n),window.CKOConfig={publicKey:document.querySelector('meta[name="public-key"]').content,customerEmail:document.querySelector('meta[name="customer-email"]').content,value:document.querySelector('meta[name="value"]').content,currency:document.querySelector('meta[name="currency"]').content,paymentMode:"cards",cardFormMode:"cardTokenisation",cardTokenised:function(e){n(e)}}}});

View File

@ -1,2 +1,112 @@
/*! For license information please see process.js.LICENSE.txt */ /******/ (function(modules) { // webpackBootstrap
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=12)}({12:function(e,t,n){e.exports=n("OXGg")},OXGg:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}new(function(){function e(t,n){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.key=t,this.usingToken=n}var t,r,o;return t=e,(r=[{key:"setupStripe",value:function(){return this.stripe=Stripe(this.key),this.elements=this.stripe.elements(),this}},{key:"createElement",value:function(){return this.cardElement=this.elements.create("card"),this}},{key:"mountCardElement",value:function(){return this.cardElement.mount("#card-element"),this}},{key:"completePaymentUsingToken",value:function(){var e=this,t=document.getElementById("pay-now-with-token");this.payNowButton=t,this.payNowButton.disabled=!0,this.payNowButton.querySelector("svg").classList.remove("hidden"),this.payNowButton.querySelector("span").classList.add("hidden"),this.stripe.handleCardPayment(t.dataset.secret,{payment_method:t.dataset.token}).then((function(t){return t.error?e.handleFailure(t.error.message):e.handleSuccess(t)}))}},{key:"completePaymentWithoutToken",value:function(){var e=this,t=document.getElementById("pay-now");this.payNowButton=t,this.payNowButton.disabled=!0,this.payNowButton.querySelector("svg").classList.remove("hidden"),this.payNowButton.querySelector("span").classList.add("hidden");var n=document.getElementById("cardholder-name");this.stripe.handleCardPayment(t.dataset.secret,this.cardElement,{payment_method_data:{billing_details:{name:n.value}}}).then((function(t){return t.error?e.handleFailure(t.error.message):e.handleSuccess(t)}))}},{key:"handleSuccess",value:function(e){document.querySelector('input[name="gateway_response"]').value=JSON.stringify(e.paymentIntent);var t=document.querySelector('input[name="token-billing-checkbox"]');t&&(document.querySelector('input[name="store_card"]').value=t.checked),document.getElementById("server-response").submit()}},{key:"handleFailure",value:function(e){var t=document.getElementById("errors");t.textContent="",t.textContent=e,t.hidden=!1,this.payNowButton.disabled=!1,this.payNowButton.querySelector("svg").classList.add("hidden"),this.payNowButton.querySelector("span").classList.remove("hidden")}},{key:"handle",value:function(){var e=this;this.setupStripe(),this.usingToken&&document.getElementById("pay-now-with-token").addEventListener("click",(function(){return e.completePaymentUsingToken()})),this.usingToken||(this.createElement().mountCardElement(),document.getElementById("pay-now").addEventListener("click",(function(){return e.completePaymentWithoutToken()})))}}])&&n(t.prototype,r),o&&n(t,o),e}())(document.querySelector('meta[name="stripe-publishable-key"]').content,document.querySelector('meta[name="using-token"]').content).handle()}}); /******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "/";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 12);
/******/ })
/************************************************************************/
/******/ ({
/***/ "./resources/js/clients/payments/process.js":
/*!**************************************************!*\
!*** ./resources/js/clients/payments/process.js ***!
\**************************************************/
/*! no static exports found */
/***/ (function(module, exports) {
throw new Error("Module build failed (from ./node_modules/babel-loader/lib/index.js):\nError: ENOENT: no such file or directory, open '/home/benjamin/Development/invoiceninja/resources/js/clients/payments/process.js'");
/***/ }),
/***/ 12:
/*!********************************************************!*\
!*** multi ./resources/js/clients/payments/process.js ***!
\********************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(/*! /home/benjamin/Development/invoiceninja/resources/js/clients/payments/process.js */"./resources/js/clients/payments/process.js");
/***/ })
/******/ });

View File

@ -1,2 +1,112 @@
/*! For license information please see sofort.js.LICENSE.txt */ /******/ (function(modules) { // webpackBootstrap
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=7)}({7:function(e,t,n){e.exports=n("Zfcc")},Zfcc:function(e,t){function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}new function e(t){var r=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),n(this,"setupStripe",(function(){return r.stripe=Stripe(r.key),r})),n(this,"handle",(function(){var e={type:"sofort",amount:document.querySelector('meta[name="amount"]').content,currency:"eur",redirect:{return_url:document.querySelector('meta[name="return-url"]').content},sofort:{country:document.querySelector('meta[name="country"').content}};document.getElementById("pay-now").addEventListener("submit",(function(t){t.preventDefault(),document.getElementById("pay-now-button").disabled=!0,document.querySelector("#pay-now-button > svg").classList.remove("hidden"),document.querySelector("#pay-now-button > span").classList.add("hidden"),r.stripe.createSource(e).then((function(e){if(e.hasOwnProperty("source"))return window.location=e.source.redirect.url;document.getElementById("pay-now-button").disabled=!1,document.querySelector("#pay-now-button > svg").classList.add("hidden"),document.querySelector("#pay-now-button > span").classList.remove("hidden"),this.errors.textContent="",this.errors.textContent=e.error.message,this.errors.hidden=!1,processingOverlay(!1),document.getElementById("pay-now").disabled=!1}))}))})),this.key=t,this.errors=document.getElementById("errors")}(document.querySelector('meta[name="stripe-publishable-key"]').content).setupStripe().handle()}}); /******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "/";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 6);
/******/ })
/************************************************************************/
/******/ ({
/***/ "./resources/js/clients/payments/sofort.js":
/*!*************************************************!*\
!*** ./resources/js/clients/payments/sofort.js ***!
\*************************************************/
/*! no static exports found */
/***/ (function(module, exports) {
throw new Error("Module build failed (from ./node_modules/babel-loader/lib/index.js):\nError: ENOENT: no such file or directory, open '/home/benjamin/Development/invoiceninja/resources/js/clients/payments/sofort.js'");
/***/ }),
/***/ 6:
/*!*******************************************************!*\
!*** multi ./resources/js/clients/payments/sofort.js ***!
\*******************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(/*! /home/benjamin/Development/invoiceninja/resources/js/clients/payments/sofort.js */"./resources/js/clients/payments/sofort.js");
/***/ })
/******/ });

View File

@ -0,0 +1,2 @@
/*! For license information please see stripe-ach.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=3)}({3:function(e,t,n){e.exports=n("M5il")},M5il:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}(new(function(){function e(){var t=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),r(this,"setupStripe",(function(){return t.stripe=Stripe(t.key),t})),r(this,"getFormData",(function(){return{country:document.getElementById("country").value,currency:document.getElementById("currency").value,routing_number:document.getElementById("routing-number").value,account_number:document.getElementById("account-number").value,account_holder_name:document.getElementById("account-holder-name").value,account_holder_type:document.querySelector('input[name="account-holder-type"]:checked').value}})),r(this,"handleError",(function(e){document.getElementById("save-button").disabled=!1,document.querySelector("#save-button > svg").classList.add("hidden"),document.querySelector("#save-button > span").classList.remove("hidden"),t.errors.textContent="",t.errors.textContent=e,t.errors.hidden=!1})),r(this,"handleSuccess",(function(e){document.getElementById("gateway_response").value=JSON.stringify(e),document.getElementById("server_response").submit()})),r(this,"handleSubmit",(function(e){document.getElementById("save-button").disabled=!0,document.querySelector("#save-button > svg").classList.remove("hidden"),document.querySelector("#save-button > span").classList.add("hidden"),e.preventDefault(),t.errors.textContent="",t.errors.hidden=!0,t.stripe.createToken("bank_account",t.getFormData()).then((function(e){return e.hasOwnProperty("error")?t.handleError(e.error.message):t.handleSuccess(e)}))})),this.errors=document.getElementById("errors"),this.key=document.querySelector('meta[name="stripe-publishable-key"]').content}var t,o,u;return t=e,(o=[{key:"handle",value:function(){var e=this;document.getElementById("save-button").addEventListener("click",(function(t){return e.handleSubmit(t)}))}}])&&n(t.prototype,o),u&&n(t,u),e}())).setupStripe().handle()}});

View File

@ -0,0 +1,9 @@
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/

View File

@ -0,0 +1,2 @@
/*! For license information please see stripe-alipay.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=7)}({"+keB":function(e,t){function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}new function e(t){var r=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),n(this,"setupStripe",(function(){return r.stripe=Stripe(r.key),r})),n(this,"handle",(function(){var e={type:"alipay",amount:document.querySelector('meta[name="amount"]').content,currency:document.querySelector('meta[name="currency"]').content,redirect:{return_url:document.querySelector('meta[name="return-url"]').content}};document.getElementById("pay-now").addEventListener("click",(function(t){document.getElementById("pay-now-button").disabled=!0,document.querySelector("#pay-now-button > svg").classList.add("hidden"),document.querySelector("#pay-now-button > span").classList.remove("hidden"),r.stripe.createSource(e).then((function(e){if(e.hasOwnProperty("source"))return window.location=e.source.redirect.url;document.getElementById("pay-now-button").disabled=!1,document.querySelector("#pay-now-button > svg").classList.remove("hidden"),document.querySelector("#pay-now-button > span").classList.add("hidden"),this.errors.textContent="",this.errors.textContent=e.error.message,this.errors.hidden=!1}))}))})),this.key=t,this.errors=document.getElementById("errors")}(document.querySelector('meta[name="stripe-publishable-key"]').content).setupStripe().handle()},7:function(e,t,n){e.exports=n("+keB")}});

View File

@ -0,0 +1,9 @@
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/

View File

@ -0,0 +1,2 @@
/*! For license information please see stripe-credit-card.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=11)}({11:function(e,t,n){e.exports=n("uALE")},uALE:function(e,t){var n,r,o,i;function a(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}new(function(){function e(t,n,r,o){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.key=t,this.token=n,this.secret=r,this.onlyAuthorization=o}var t,n,r;return t=e,(n=[{key:"setupStripe",value:function(){return this.stripe=Stripe(this.key),this.elements=this.stripe.elements(),this}},{key:"createElement",value:function(){return this.cardElement=this.elements.create("card"),this}},{key:"mountCardElement",value:function(){return this.cardElement.mount("#card-element"),this}},{key:"completePaymentUsingToken",value:function(){var e=this,t=document.getElementById("pay-now-with-token");this.payNowButton=t,this.payNowButton.disabled=!0,this.payNowButton.querySelector("svg").classList.remove("hidden"),this.payNowButton.querySelector("span").classList.add("hidden"),this.stripe.handleCardPayment(this.secret,{payment_method:this.token}).then((function(t){return t.error?e.handleFailure(t.error.message):e.handleSuccess(t)}))}},{key:"completePaymentWithoutToken",value:function(){var e=this,t=document.getElementById("pay-now");this.payNowButton=t,this.payNowButton.disabled=!0,this.payNowButton.querySelector("svg").classList.remove("hidden"),this.payNowButton.querySelector("span").classList.add("hidden");var n=document.getElementById("cardholder-name");this.stripe.handleCardPayment(this.secret,this.cardElement,{payment_method_data:{billing_details:{name:n.value}}}).then((function(t){return t.error?e.handleFailure(t.error.message):e.handleSuccess(t)}))}},{key:"handleSuccess",value:function(e){document.querySelector('input[name="gateway_response"]').value=JSON.stringify(e.paymentIntent);var t=document.querySelector('input[name="token-billing-checkbox"]');t&&(document.querySelector('input[name="store_card"]').value=t.checked),document.getElementById("server-response").submit()}},{key:"handleFailure",value:function(e){var t=document.getElementById("errors");t.textContent="",t.textContent=e,t.hidden=!1,this.payNowButton.disabled=!1,this.payNowButton.querySelector("svg").classList.add("hidden"),this.payNowButton.querySelector("span").classList.remove("hidden")}},{key:"handleAuthorization",value:function(){var e=this,t=document.getElementById("cardholder-name"),n=document.getElementById("authorize-card");this.payNowButton=n,this.payNowButton.disabled=!0,this.payNowButton.querySelector("svg").classList.remove("hidden"),this.payNowButton.querySelector("span").classList.add("hidden"),this.stripe.handleCardSetup(this.secret,this.cardElement,{payment_method_data:{billing_details:{name:t.value}}}).then((function(t){return t.error?e.handleFailure(t):e.handleSuccessfulAuthorization(t)}))}},{key:"handleSuccessfulAuthorization",value:function(e){document.getElementById("gateway_response").value=JSON.stringify(e.setupIntent),document.getElementById("server_response").submit()}},{key:"handle",value:function(){var e=this;this.setupStripe(),this.onlyAuthorization?(this.createElement().mountCardElement(),document.getElementById("authorize-card").addEventListener("click",(function(){return e.handleAuthorization()}))):(this.token&&document.getElementById("pay-now-with-token").addEventListener("click",(function(){return e.completePaymentUsingToken()})),this.token||(this.createElement().mountCardElement(),document.getElementById("pay-now").addEventListener("click",(function(){return e.completePaymentWithoutToken()}))))}}])&&a(t.prototype,n),r&&a(t,r),e}())(null!==(n=document.querySelector('meta[name="stripe-publishable-key"]').content)&&void 0!==n?n:"",null!==(r=document.querySelector('meta[name="stripe-token"]').content)&&void 0!==r?r:"",null!==(o=document.querySelector('meta[name="stripe-secret"]').content)&&void 0!==o?o:"",null!==(i=document.querySelector('meta[name="only-authorization"]').content)&&void 0!==i?i:"").handle()}});

View File

@ -0,0 +1,9 @@
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/

View File

@ -0,0 +1,2 @@
/*! For license information please see stripe-sofort.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=6)}({6:function(e,t,n){e.exports=n("RFiP")},RFiP:function(e,t){function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}new function e(t){var r=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),n(this,"setupStripe",(function(){return r.stripe=Stripe(r.key),r})),n(this,"handle",(function(){var e={type:"sofort",amount:document.querySelector('meta[name="amount"]').content,currency:"eur",redirect:{return_url:document.querySelector('meta[name="return-url"]').content},sofort:{country:document.querySelector('meta[name="country"').content}};document.getElementById("pay-now").addEventListener("click",(function(t){document.getElementById("pay-now-button").disabled=!0,document.querySelector("#pay-now-button > svg").classList.remove("hidden"),document.querySelector("#pay-now-button > span").classList.add("hidden"),r.stripe.createSource(e).then((function(e){if(e.hasOwnProperty("source"))return window.location=e.source.redirect.url;document.getElementById("pay-now-button").disabled=!1,document.querySelector("#pay-now-button > svg").classList.add("hidden"),document.querySelector("#pay-now-button > span").classList.remove("hidden"),this.errors.textContent="",this.errors.textContent=e.error.message,this.errors.hidden=!1,document.getElementById("pay-now").disabled=!1}))}))})),this.key=t,this.errors=document.getElementById("errors")}(document.querySelector('meta[name="stripe-publishable-key"]').content).setupStripe().handle()}});

View File

@ -0,0 +1,9 @@
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/

View File

@ -1,2 +1,2 @@
/*! For license information please see action-selectors.js.LICENSE.txt */ /*! For license information please see action-selectors.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=10)}({10:function(e,t,n){e.exports=n("ydWM")},ydWM:function(e,t){function n(e,t){var n;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(n=function(e,t){if(!e)return;if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return r(e,t)}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var o=0,c=function(){};return{s:c,n:function(){return o>=e.length?{done:!0}:{done:!1,value:e[o++]}},e:function(e){throw e},f:c}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var u,i=!0,l=!1;return{s:function(){n=e[Symbol.iterator]()},n:function(){var e=n.next();return i=e.done,e},e:function(e){l=!0,u=e},f:function(){try{i||null==n.return||n.return()}finally{if(l)throw u}}}}function r(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function o(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}(new(function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.parentElement=document.querySelector(".form-check-parent"),this.parentForm=document.getElementById("bulkActions")}var t,r,c;return t=e,(r=[{key:"watchCheckboxes",value:function(e){var t=this;document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})),document.querySelectorAll(".form-check-child").forEach((function(n){e.checked?(n.checked=e.checked,t.processChildItem(n,document.getElementById("bulkActions"))):(n.checked=!1,document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})))}))}},{key:"processChildItem",value:function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(r.hasOwnProperty("single")&&document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})),!1!==e.checked){var o=document.createElement("INPUT");o.setAttribute("name","invoices[]"),o.setAttribute("value",e.dataset.value),o.setAttribute("class","child-hidden-input"),o.hidden=!0,t.append(o)}else{var c,u=document.querySelectorAll("input.child-hidden-input"),i=n(u);try{for(i.s();!(c=i.n()).done;){var l=c.value;l.value==e.dataset.value&&l.remove()}}catch(e){i.e(e)}finally{i.f()}}}},{key:"handle",value:function(){var e=this;this.parentElement.addEventListener("click",(function(){e.watchCheckboxes(e.parentElement)}));var t,r=n(document.querySelectorAll(".form-check-child"));try{var o=function(){var n=t.value;n.addEventListener("click",(function(){e.processChildItem(n,e.parentForm)}))};for(r.s();!(t=r.n()).done;)o()}catch(e){r.e(e)}finally{r.f()}}}])&&o(t.prototype,r),c&&o(t,c),e}())).handle()}}); !function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=9)}({9:function(e,t,n){e.exports=n("ydWM")},ydWM:function(e,t){function n(e,t){var n;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(n=function(e,t){if(!e)return;if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return r(e,t)}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var o=0,c=function(){};return{s:c,n:function(){return o>=e.length?{done:!0}:{done:!1,value:e[o++]}},e:function(e){throw e},f:c}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var u,i=!0,l=!1;return{s:function(){n=e[Symbol.iterator]()},n:function(){var e=n.next();return i=e.done,e},e:function(e){l=!0,u=e},f:function(){try{i||null==n.return||n.return()}finally{if(l)throw u}}}}function r(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function o(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}(new(function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.parentElement=document.querySelector(".form-check-parent"),this.parentForm=document.getElementById("bulkActions")}var t,r,c;return t=e,(r=[{key:"watchCheckboxes",value:function(e){var t=this;document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})),document.querySelectorAll(".form-check-child").forEach((function(n){e.checked?(n.checked=e.checked,t.processChildItem(n,document.getElementById("bulkActions"))):(n.checked=!1,document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})))}))}},{key:"processChildItem",value:function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(r.hasOwnProperty("single")&&document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})),!1!==e.checked){var o=document.createElement("INPUT");o.setAttribute("name","invoices[]"),o.setAttribute("value",e.dataset.value),o.setAttribute("class","child-hidden-input"),o.hidden=!0,t.append(o)}else{var c,u=document.querySelectorAll("input.child-hidden-input"),i=n(u);try{for(i.s();!(c=i.n()).done;){var l=c.value;l.value==e.dataset.value&&l.remove()}}catch(e){i.e(e)}finally{i.f()}}}},{key:"handle",value:function(){var e=this;this.parentElement.addEventListener("click",(function(){e.watchCheckboxes(e.parentElement)}));var t,r=n(document.querySelectorAll(".form-check-child"));try{var o=function(){var n=t.value;n.addEventListener("click",(function(){e.processChildItem(n,e.parentForm)}))};for(r.s();!(t=r.n()).done;)o()}catch(e){r.e(e)}finally{r.f()}}}])&&o(t.prototype,r),c&&o(t,c),e}())).handle()}});

View File

@ -1,2 +1,2 @@
/*! For license information please see approve.js.LICENSE.txt */ /*! For license information please see approve.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=11)}({11:function(e,t,n){e.exports=n("WuMn")},WuMn:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var r=function(){function e(t){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.shouldDisplaySignature=t}var t,r,o;return t=e,(r=[{key:"submitForm",value:function(){document.getElementById("approve-form").submit()}},{key:"displaySignature",value:function(){document.getElementById("displaySignatureModal").removeAttribute("style"),new SignaturePad(document.getElementById("signature-pad"),{backgroundColor:"rgb(240,240,240)",penColor:"rgb(0, 0, 0)"})}},{key:"handle",value:function(){var e=this;document.getElementById("approve-button").addEventListener("click",(function(){e.shouldDisplaySignature&&(e.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){e.submitForm()}))),e.shouldDisplaySignature||e.submitForm()}))}}])&&n(t.prototype,r),o&&n(t,o),e}(),o=document.querySelector('meta[name="require-quote-signature"]').content;new r(Boolean(+o)).handle()}}); !function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=10)}({10:function(e,t,n){e.exports=n("WuMn")},WuMn:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var r=function(){function e(t){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.shouldDisplaySignature=t}var t,r,o;return t=e,(r=[{key:"submitForm",value:function(){document.getElementById("approve-form").submit()}},{key:"displaySignature",value:function(){document.getElementById("displaySignatureModal").removeAttribute("style"),new SignaturePad(document.getElementById("signature-pad"),{backgroundColor:"rgb(240,240,240)",penColor:"rgb(0, 0, 0)"})}},{key:"handle",value:function(){var e=this;document.getElementById("approve-button").addEventListener("click",(function(){e.shouldDisplaySignature&&(e.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){e.submitForm()}))),e.shouldDisplaySignature||e.submitForm()}))}}])&&n(t.prototype,r),o&&n(t,o),e}(),o=document.querySelector('meta[name="require-quote-signature"]').content;new r(Boolean(+o)).handle()}});

View File

@ -1 +1 @@
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=16)}({16:function(e,t,n){e.exports=n("W54t")},W54t:function(e,t){window.appendToElement=function(e,t){var n=document.getElementById(e),r=n.querySelector('input[value="'.concat(t,'"]'));if(r)return r.remove();var o=document.createElement("INPUT");o.setAttribute("name","file_hash[]"),o.setAttribute("value",t),o.hidden=!0,n.append(o)}}}); !function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=15)}({15:function(e,t,n){e.exports=n("W54t")},W54t:function(e,t){window.appendToElement=function(e,t){var n=document.getElementById(e),r=n.querySelector('input[value="'.concat(t,'"]'));if(r)return r.remove();var o=document.createElement("INPUT");o.setAttribute("name","file_hash[]"),o.setAttribute("value",t),o.hidden=!0,n.append(o)}}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,21 +1,20 @@
{ {
"/js/app.js": "/js/app.js?id=a33a5a58bfc6e2174841", "/js/app.js": "/js/app.js?id=a33a5a58bfc6e2174841",
"/css/app.css": "/css/app.css?id=0bd4f816cc00fc0faae6", "/css/app.css": "/css/app.css?id=d338d4916fca469819c3",
"/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=b0f29d5fdfa492962c22", "/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=a09bb529b8e1826f13b4",
"/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=d7e708d66a9c769b4c6e", "/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=8ce8955ba775ea5f47d1",
"/js/clients/payment_methods/authorize-ach.js": "/js/clients/payment_methods/authorize-ach.js?id=c73d32c192c36fe44123", "/js/clients/payment_methods/authorize-authorize-card.js": "/js/clients/payment_methods/authorize-authorize-card.js?id=cddcd46c630c71737bda",
"/js/clients/payment_methods/authorize-authorize-card.js": "/js/clients/payment_methods/authorize-authorize-card.js?id=044dc1eabd2ee074cb2b", "/js/clients/payments/authorize-credit-card-payment.js": "/js/clients/payments/authorize-credit-card-payment.js?id=0b6329de6fcb70186f64",
"/js/clients/payment_methods/authorize-stripe-card.js": "/js/clients/payment_methods/authorize-stripe-card.js?id=b1389b07a0fdb263308f", "/js/clients/payments/card-js.min.js": "/js/clients/payments/card-js.min.js?id=5469146cd629ea1b5c20",
"/js/clients/payments/alipay.js": "/js/clients/payments/alipay.js?id=6be66f65ec4537b3b05e", "/js/clients/payments/checkout.com.js": "/js/clients/payments/checkout.com.js?id=4d5d992da65a0c422291",
"/js/clients/payments/authorize-credit-card-payment.js": "/js/clients/payments/authorize-credit-card-payment.js?id=80605d1869d3b97c5090", "/js/clients/payments/stripe-ach.js": "/js/clients/payments/stripe-ach.js?id=c4012ad90f17d60432ad",
"/js/clients/payments/card-js.min.js": "/js/clients/payments/card-js.min.js?id=7200ac43b87bddf1bedc", "/js/clients/payments/stripe-alipay.js": "/js/clients/payments/stripe-alipay.js?id=37404fa506870a7451a4",
"/js/clients/payments/checkout.com.js": "/js/clients/payments/checkout.com.js?id=bee8407bd5dfae80dc6a", "/js/clients/payments/stripe-credit-card.js": "/js/clients/payments/stripe-credit-card.js?id=f4659d26a26d2f408397",
"/js/clients/payments/process.js": "/js/clients/payments/process.js?id=734f91dd5526b30adb2a", "/js/clients/payments/stripe-sofort.js": "/js/clients/payments/stripe-sofort.js?id=7f5b13e34c75e63c015e",
"/js/clients/payments/sofort.js": "/js/clients/payments/sofort.js?id=946855f32f6f44ab25be", "/js/clients/quotes/action-selectors.js": "/js/clients/quotes/action-selectors.js?id=16dfb55f9387a3b6e752",
"/js/clients/quotes/action-selectors.js": "/js/clients/quotes/action-selectors.js?id=1702ddb9f59521c7758f", "/js/clients/quotes/approve.js": "/js/clients/quotes/approve.js?id=9cdbe50bab63dc1dd520",
"/js/clients/quotes/approve.js": "/js/clients/quotes/approve.js?id=1c5d76fb5f98bd49f6c8", "/js/clients/shared/multiple-downloads.js": "/js/clients/shared/multiple-downloads.js?id=5c35d28cf0a3286e7c45",
"/js/clients/shared/multiple-downloads.js": "/js/clients/shared/multiple-downloads.js?id=bf87649ca30c9a3fba59", "/js/clients/shared/pdf.js": "/js/clients/shared/pdf.js?id=fa54bb4229aba6b0817c",
"/js/clients/shared/pdf.js": "/js/clients/shared/pdf.js?id=df93e290245c26694fdb", "/js/setup/setup.js": "/js/setup/setup.js?id=f42b2dee6575623822c2",
"/js/setup/setup.js": "/js/setup/setup.js?id=e8de60f3af6b10afe483",
"/css/card-js.min.css": "/css/card-js.min.css?id=62afeb675235451543ad" "/css/card-js.min.css": "/css/card-js.min.css?id=62afeb675235451543ad"
} }

View File

@ -1,99 +0,0 @@
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
class AuthorizeStripeCard {
constructor(key) {
this.key = key;
this.cardHolderName = document.getElementById('cardholder-name');
this.cardButton = document.getElementById('card-button');
this.clientSecret = this.cardButton.dataset.secret;
}
setupStripe() {
this.stripe = Stripe(this.key);
this.elements = this.stripe.elements();
return this;
}
createElement() {
this.cardElement = this.elements.create('card');
return this;
}
mountCardElement() {
this.cardElement.mount('#card-element');
return this;
}
handleStripe(stripe, cardHolderName) {
this.cardButton.disabled = true;
this.cardButton.querySelector('span').classList.add('hidden');
this.cardButton.querySelector('svg').classList.remove('hidden');
stripe
.handleCardSetup(this.clientSecret, this.cardElement, {
payment_method_data: {
billing_details: { name: cardHolderName.value },
},
})
.then((result) => {
if (result.error) {
return this.handleFailure(result);
}
return this.handleSuccess(result);
});
}
handleFailure(result) {
this.cardButton.disabled = false;
this.cardButton.querySelector('span').classList.remove('hidden');
this.cardButton.querySelector('svg').classList.add('hidden');
let errors = document.getElementById('errors');
errors.textContent = '';
errors.textContent = result.error.message;
errors.hidden = false;
}
handleSuccess(result) {
document.getElementById('gateway_response').value = JSON.stringify(
result.setupIntent
);
document.getElementById('is_default').value = document.getElementById(
'proxy_is_default'
).checked;
document.getElementById('server_response').submit();
}
handle() {
this.setupStripe()
.createElement()
.mountCardElement();
this.cardButton.addEventListener('click', () => {
this.handleStripe(this.stripe, this.cardHolderName);
});
return this;
}
}
const publishableKey = document.querySelector(
'meta[name="stripe-publishable-key"]'
).content;
/** @handle */
new AuthorizeStripeCard(publishableKey).handle();

View File

@ -8,6 +8,48 @@
* @license https://opensource.org/licenses/AAL * @license https://opensource.org/licenses/AAL
*/ */
document
.getElementById('toggle-payment-with-token')
.addEventListener('click', () => {
document.getElementById('save-card--container').style.display = 'none';
document.getElementById('checkout--container').style.display = 'none';
document.getElementById('pay-now-with-token--container').style.display =
'block';
document.querySelector('input[name=pay_with_token]').value = true;
});
document
.getElementById('toggle-payment-with-credit-card')
.addEventListener('click', () => {
document.getElementById('save-card--container').style.display = 'grid';
document.getElementById('checkout--container').style.display = 'block';
document.getElementById('pay-now-with-token--container').style.display =
'none';
document.querySelector('input[name=pay_with_token]').value = false;
});
const completePayment = (data = null) => {
if (data) {
document.querySelector(
'input[name="gateway_response"]'
).value = JSON.stringify(data.data);
}
document.querySelector(
'input[name="store_card"]'
).value = document.querySelector(
'input[name=token-billing-checkbox]:checked'
).value;
document.getElementById('server-response').submit();
};
document
.getElementById('pay-now-with-token')
.addEventListener('click', completePayment);
window.CKOConfig = { window.CKOConfig = {
publicKey: document.querySelector('meta[name="public-key"]').content, publicKey: document.querySelector('meta[name="public-key"]').content,
customerEmail: document.querySelector('meta[name="customer-email"]') customerEmail: document.querySelector('meta[name="customer-email"]')
@ -17,14 +59,6 @@ window.CKOConfig = {
paymentMode: 'cards', paymentMode: 'cards',
cardFormMode: 'cardTokenisation', cardFormMode: 'cardTokenisation',
cardTokenised: function(event) { cardTokenised: function(event) {
document.querySelector( completePayment(event);
'input[name="gateway_response"]'
).value = JSON.stringify(event.data);
document.querySelector(
'input[name="store_card"]'
).value = document.querySelector('input[name=token-billing-checkbox]:checked').value;
document.getElementById('server-response').submit();
}, },
}; };

View File

@ -77,8 +77,8 @@ class AuthorizeACH {
handle() { handle() {
document document
.getElementById('token-form') .getElementById('save-button')
.addEventListener('submit', (e) => this.handleSubmit(e)); .addEventListener('click', (e) => this.handleSubmit(e));
} }
} }

View File

@ -31,9 +31,7 @@ class ProcessAlipay {
}, },
}; };
document.getElementById('pay-now').addEventListener('submit', (e) => { document.getElementById('pay-now').addEventListener('click', (e) => {
e.preventDefault();
document.getElementById('pay-now-button').disabled = true; document.getElementById('pay-now-button').disabled = true;
document.querySelector('#pay-now-button > svg').classList.add('hidden'); document.querySelector('#pay-now-button > svg').classList.add('hidden');
document.querySelector('#pay-now-button > span').classList.remove('hidden'); document.querySelector('#pay-now-button > span').classList.remove('hidden');

View File

@ -8,10 +8,12 @@
* @license https://opensource.org/licenses/AAL * @license https://opensource.org/licenses/AAL
*/ */
class ProcessStripePayment { class StripeCreditCard {
constructor(key, usingToken) { constructor(key, token, secret, onlyAuthorization) {
this.key = key; this.key = key;
this.usingToken = usingToken; this.token = token;
this.secret = secret;
this.onlyAuthorization = onlyAuthorization;
} }
setupStripe() { setupStripe() {
@ -43,8 +45,8 @@ class ProcessStripePayment {
this.payNowButton.querySelector('span').classList.add('hidden'); this.payNowButton.querySelector('span').classList.add('hidden');
this.stripe this.stripe
.handleCardPayment(payNowButton.dataset.secret, { .handleCardPayment(this.secret, {
payment_method: payNowButton.dataset.token, payment_method: this.token,
}) })
.then((result) => { .then((result) => {
if (result.error) { if (result.error) {
@ -67,7 +69,7 @@ class ProcessStripePayment {
let cardHolderName = document.getElementById('cardholder-name'); let cardHolderName = document.getElementById('cardholder-name');
this.stripe this.stripe
.handleCardPayment(payNowButton.dataset.secret, this.cardElement, { .handleCardPayment(this.secret, this.cardElement, {
payment_method_data: { payment_method_data: {
billing_details: { name: cardHolderName.value }, billing_details: { name: cardHolderName.value },
}, },
@ -110,31 +112,82 @@ class ProcessStripePayment {
this.payNowButton.querySelector('span').classList.remove('hidden'); this.payNowButton.querySelector('span').classList.remove('hidden');
} }
handleAuthorization() {
let cardHolderName = document.getElementById('cardholder-name');
let payNowButton = document.getElementById('authorize-card');
this.payNowButton = payNowButton;
this.payNowButton.disabled = true;
this.payNowButton.querySelector('svg').classList.remove('hidden');
this.payNowButton.querySelector('span').classList.add('hidden');
this.stripe
.handleCardSetup(this.secret, this.cardElement, {
payment_method_data: {
billing_details: { name: cardHolderName.value },
},
})
.then((result) => {
if (result.error) {
return this.handleFailure(result);
}
return this.handleSuccessfulAuthorization(result);
});
}
handleSuccessfulAuthorization(result) {
document.getElementById('gateway_response').value = JSON.stringify(
result.setupIntent
);
document.getElementById('server_response').submit();
}
handle() { handle() {
this.setupStripe(); this.setupStripe();
if (this.usingToken) { if (this.onlyAuthorization) {
document
.getElementById('pay-now-with-token')
.addEventListener('click', () => {
return this.completePaymentUsingToken();
});
}
if (!this.usingToken) {
this.createElement().mountCardElement(); this.createElement().mountCardElement();
document.getElementById('pay-now').addEventListener('click', () => { document
return this.completePaymentWithoutToken(); .getElementById('authorize-card')
}); .addEventListener('click', () => {
return this.handleAuthorization();
});
} else {
if (this.token) {
document
.getElementById('pay-now-with-token')
.addEventListener('click', () => {
return this.completePaymentUsingToken();
});
}
if (!this.token) {
this.createElement().mountCardElement();
document
.getElementById('pay-now')
.addEventListener('click', () => {
return this.completePaymentWithoutToken();
});
}
} }
} }
} }
const publishableKey = document.querySelector( const publishableKey =
'meta[name="stripe-publishable-key"]' document.querySelector('meta[name="stripe-publishable-key"]').content ?? '';
).content;
const usingToken = document.querySelector('meta[name="using-token"]').content; const token = document.querySelector('meta[name="stripe-token"]').content ?? '';
new ProcessStripePayment(publishableKey, usingToken).handle(); const secret =
document.querySelector('meta[name="stripe-secret"]').content ?? '';
const onlyAuthorization =
document.querySelector('meta[name="only-authorization"]').content ?? '';
new StripeCreditCard(publishableKey, token, secret, onlyAuthorization).handle();

View File

@ -34,9 +34,7 @@ class ProcessSOFORT {
}, },
}; };
document.getElementById('pay-now').addEventListener('submit', (e) => { document.getElementById('pay-now').addEventListener('click', (e) => {
e.preventDefault();
document.getElementById('pay-now-button').disabled = true; document.getElementById('pay-now-button').disabled = true;
document.querySelector('#pay-now-button > svg').classList.remove('hidden'); document.querySelector('#pay-now-button > svg').classList.remove('hidden');
document.querySelector('#pay-now-button > span').classList.add('hidden'); document.querySelector('#pay-now-button > span').classList.add('hidden');
@ -54,8 +52,6 @@ class ProcessSOFORT {
this.errors.textContent = result.error.message; this.errors.textContent = result.error.message;
this.errors.hidden = false; this.errors.hidden = false;
processingOverlay(false);
document.getElementById('pay-now').disabled = false; document.getElementById('pay-now').disabled = false;
}); });
}); });

View File

@ -3288,5 +3288,10 @@ return [
'payment_type_Crypto' => 'Cryptocurrency', 'payment_type_Crypto' => 'Cryptocurrency',
'payment_type_Credit' => 'Credit', 'payment_type_Credit' => 'Credit',
'store_for_future_use' => 'Store for future use',
'pay_with_credit' => 'Pay with credit',
'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',
]; ];

View File

@ -0,0 +1,5 @@
<div class="px-4 py-5 sm:px-6">
<dt class="text-sm leading-5 font-medium">
{{ $slot }}
</dt>
</div>

View File

@ -0,0 +1,8 @@
<div class="px-4 py-5 sm:px-6 lg:grid lg:grid-cols-3 lg:gap-4 lg:flex lg:items-center">
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4">
{{ $title }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
{{ $slot }}
</dd>
</div>

View File

@ -0,0 +1,128 @@
@extends('portal.ninja2020.layout.app')
@section('meta_title', ctrans('texts.checkout_com'))
@push('head')
<meta name="public-key" content="{{ $gateway->getPublishableKey() }}">
<meta name="customer-email" content="{{ $customer_email }}">
<meta name="value" content="{{ $value }}">
<meta name="currency" content="{{ $currency }}">
<meta name="reference" content="{{ $payment_hash }}">
<script src="{{ asset('js/clients/payments/checkout.com.js') }}"></script>
@endpush
@section('body')
<form action="{{ route('client.payments.response') }}" method="post" id="server-response">
@csrf
<input type="hidden" name="gateway_response">
<input type="hidden" name="store_card">
<input type="hidden" name="reference" value="{{ $payment_hash }}">
<input type="hidden" name="payment_hash" value="{{ $payment_hash }}">
<input type="hidden" name="company_gateway_id" value="{{ $company_gateway->id }}">
<input type="hidden" name="payment_method_id" value="{{ $payment_method_id }}">
<input type="hidden" name="value" value="{{ $value }}">
<input type="hidden" name="raw_value" value="{{ $raw_value }}">
<input type="hidden" name="currency" value="{{ $currency }}">
@isset($token)
<input type="hidden" name="token" value="{{ $token->meta->id }}">
@endisset
</form>
<div class="container mx-auto">
<div class="grid grid-cols-6 gap-4">
<div class="col-span-6 md:col-start-2 md:col-span-4">
<div class="alert alert-failure mb-4" hidden id="errors"></div>
<div class="bg-white shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 border-b border-gray-200 sm:px-6">
<h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.pay_now') }}
</h3>
<p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500">
{{ ctrans('texts.complete_your_payment') }}
</p>
</div>
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center">
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4">
{{ ctrans('texts.payment_type') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
{{ ctrans('texts.checkout_com') }} ({{ ctrans('texts.credit_card') }})
</dd>
</div>
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center">
<dt class="text-sm leading-5 font-medium text-gray-500">
{{ ctrans('texts.subtotal') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
{{ App\Utils\Number::formatMoney($total['invoice_totals'], $client) }}
</dd>
<dt class="text-sm leading-5 font-medium text-gray-500">
{{ ctrans('texts.gateway_fees') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
{{ App\Utils\Number::formatMoney($total['fee_total'], $client) }}
</dd>
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4">
{{ ctrans('texts.amount') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<span class="font-bold">{{ App\Utils\Number::formatMoney($total['amount_with_fee'], $client) }}</span>
</dd>
</div>
@isset($token)
<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.card_number') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
**** {{ ucfirst($token->meta->last4) }}
</dd>
</div>
<div class="bg-white px-4 py-5 flex justify-end">
<button class="button button-primary bg-primary" onclick="document.getElementById('server-response').submit()">
{{ ctrans('texts.pay_now') }}
</button>
</div>
@else
<div class="{{ ($gateway->company_gateway->token_billing == 'optin' || $gateway->company_gateway->token_billing == 'optout') ? 'sm:grid' : 'hidden' }} bg-gray-50 px-4 py-5 sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm leading-5 font-medium text-gray-500">
{{ ctrans('texts.token_billing_checkbox') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<label class="mr-4">
<input
type="radio"
class="form-radio cursor-pointer"
name="token-billing-checkbox"
id="proxy_is_default"
value="true"
{{ ($gateway->company_gateway->token_billing == 'always' || $gateway->company_gateway->token_billing == 'optout') ? 'checked' : '' }} />
<span class="ml-1 cursor-pointer">{{ ctrans('texts.yes') }}</span>
</label>
<label>
<input
type="radio"
class="form-radio cursor-pointer"
name="token-billing-checkbox"
id="proxy_is_default"
value="false"
{{ ($gateway->company_gateway->token_billing == 'off' || $gateway->company_gateway->token_billing == 'optin') ? 'checked' : '' }} />
<span class="ml-1 cursor-pointer">{{ ctrans('texts.no') }}</span>
</label>
</dd>
</div>
<div class="bg-white px-4 py-5 flex justify-end">
<form class="payment-form" method="POST" action="https://merchant.com/successUrl">
@if(app()->environment() == 'production')
<script async src="https://cdn.checkout.com/js/checkout.js"></script>
@else
<script async src="https://cdn.checkout.com/sandbox/js/checkout.js"></script>
@endif
</form>
</div>
@endisset
</div>
</div>
</div>
</div>
@endsection

View File

@ -1,19 +1,7 @@
@extends('portal.ninja2020.layout.app') @extends('portal.ninja2020.layout.payments', ['gateway_title' => 'Checkout.com', 'card_title' => 'Checkout.com'])
@section('meta_title', ctrans('texts.checkout_com'))
@section('body') @section('gateway_content')
<div class="container mx-auto"> @component('portal.ninja2020.components.general.card-element-single', ['title' => 'Checkout.com', 'show_title' => false])
<div class="grid grid-cols-6 gap-4"> {{ __('texts.checkout_authorize_label') }}
<div class="col-span-6 md:col-start-2 md:col-span-4"> @endcomponent
<div class="alert alert-failure mb-4" hidden id="errors"></div>
<div class="bg-white shadow overflow-hidden sm:rounded-lg">
<div class="bg-white px-4 py-5 sm:px-6 flex items-center">
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4">
{{ ctrans('texts.checkout_authorize_label') }}
</dt>
</div>
</div>
</div>
</div>
</div>
@endsection @endsection

View File

@ -1,17 +1,14 @@
@extends('portal.ninja2020.layout.app') @extends('portal.ninja2020.layout.payments', ['gateway_title' => 'Checkout.com', 'card_title' => 'Checkout.com'])
@section('meta_title', ctrans('texts.checkout_com'))
@push('head') @section('gateway_head')
<meta name="public-key" content="{{ $gateway->getPublishableKey() }}"> <meta name="public-key" content="{{ $gateway->getPublishableKey() }}">
<meta name="customer-email" content="{{ $customer_email }}"> <meta name="customer-email" content="{{ $customer_email }}">
<meta name="value" content="{{ $value }}"> <meta name="value" content="{{ $value }}">
<meta name="currency" content="{{ $currency }}"> <meta name="currency" content="{{ $currency }}">
<meta name="reference" content="{{ $payment_hash }}"> <meta name="reference" content="{{ $payment_hash }}">
@endsection
<script src="{{ asset('js/clients/payments/checkout.com.js') }}"></script> @section('gateway_content')
@endpush
@section('body')
<form action="{{ route('client.payments.response') }}" method="post" id="server-response"> <form action="{{ route('client.payments.response') }}" method="post" id="server-response">
@csrf @csrf
<input type="hidden" name="gateway_response"> <input type="hidden" name="gateway_response">
@ -23,106 +20,57 @@
<input type="hidden" name="value" value="{{ $value }}"> <input type="hidden" name="value" value="{{ $value }}">
<input type="hidden" name="raw_value" value="{{ $raw_value }}"> <input type="hidden" name="raw_value" value="{{ $raw_value }}">
<input type="hidden" name="currency" value="{{ $currency }}"> <input type="hidden" name="currency" value="{{ $currency }}">
<input type="hidden" name="pay_with_token" value="false">
@isset($token) @isset($token)
<input type="hidden" name="token" value="{{ $token->token }}"> <input type="hidden" name="token" value="{{ $token->token }}">
@endisset @endisset
</form> </form>
<div class="container mx-auto"> @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_type')])
<div class="grid grid-cols-6 gap-4"> {{ ctrans('texts.credit_card') }} (Checkout.com)
<div class="col-span-6 md:col-start-2 md:col-span-4"> @endcomponent
<div class="alert alert-failure mb-4" hidden id="errors"></div>
<div class="bg-white shadow overflow-hidden sm:rounded-lg"> @include('portal.ninja2020.gateways.includes.payment_details')
<div class="px-4 py-5 border-b border-gray-200 sm:px-6">
<h3 class="text-lg leading-6 font-medium text-gray-900"> @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')])
{{ ctrans('texts.pay_now') }} <label class="mr-4">
</h3> <input
<p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500"> type="radio"
{{ ctrans('texts.complete_your_payment') }} id="toggle-payment-with-token"
</p> class="form-radio cursor-pointer" name="payment-type" />
</div> <span class="ml-1 cursor-pointer">**** {{ $token->meta->last4 }}</span>
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center"> </label>
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4"> <label>
{{ ctrans('texts.payment_type') }} <input
</dt> type="radio"
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2"> id="toggle-payment-with-credit-card"
{{ ctrans('texts.checkout_com') }} ({{ ctrans('texts.credit_card') }}) class="form-radio cursor-pointer"
</dd> name="payment-type"
</div> checked/>
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center"> <span class="ml-1 cursor-pointer">{{ __('texts.credit_card') }}</span>
<dt class="text-sm leading-5 font-medium text-gray-500"> </label>
{{ ctrans('texts.subtotal') }} @endcomponent
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2"> @include('portal.ninja2020.gateways.includes.save_card')
{{ App\Utils\Number::formatMoney($total['invoice_totals'], $client) }}
</dd> @component('portal.ninja2020.components.general.card-element-single')
<dt class="text-sm leading-5 font-medium text-gray-500"> <form class="payment-form" method="POST" action="#" id="checkout--container">
{{ ctrans('texts.gateway_fees') }} @if(app()->environment() == 'production')
</dt> <script async src="https://cdn.checkout.com/js/checkout.js"></script>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2"> @else
{{ App\Utils\Number::formatMoney($total['fee_total'], $client) }} <script async src="https://cdn.checkout.com/sandbox/js/checkout.js"></script>
</dd> @endif
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4"> </form>
{{ ctrans('texts.amount') }} @endcomponent
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2"> @component('portal.ninja2020.components.general.card-element-single')
<span class="font-bold">{{ App\Utils\Number::formatMoney($total['amount_with_fee'], $client) }}</span> <div class="hidden" id="pay-now-with-token--container">
</dd> @include('portal.ninja2020.gateways.includes.pay_now', ['id' => 'pay-now-with-token'])
</div> </div>
@isset($token) @endcomponent
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"> @endsection
<dt class="text-sm leading-5 font-medium text-gray-500">
{{ ctrans('texts.card_number') }} @section('gateway_footer')
</dt> <script src="{{ asset('js/clients/payments/checkout.com.js') }}"></script>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
**** {{ ucfirst($token->meta->last4) }}
</dd>
</div>
<div class="bg-white px-4 py-5 flex justify-end">
<button class="button button-primary bg-primary" onclick="document.getElementById('server-response').submit()">
{{ ctrans('texts.pay_now') }}
</button>
</div>
@else
<div class="{{ ($gateway->company_gateway->token_billing == 'optin' || $gateway->company_gateway->token_billing == 'optout') ? 'sm:grid' : 'hidden' }} bg-gray-50 px-4 py-5 sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm leading-5 font-medium text-gray-500">
{{ ctrans('texts.token_billing_checkbox') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<label class="mr-4">
<input
type="radio"
class="form-radio cursor-pointer"
name="token-billing-checkbox"
id="proxy_is_default"
value="true"
{{ ($gateway->company_gateway->token_billing == 'always' || $gateway->company_gateway->token_billing == 'optout') ? 'checked' : '' }} />
<span class="ml-1 cursor-pointer">{{ ctrans('texts.yes') }}</span>
</label>
<label>
<input
type="radio"
class="form-radio cursor-pointer"
name="token-billing-checkbox"
id="proxy_is_default"
value="false"
{{ ($gateway->company_gateway->token_billing == 'off' || $gateway->company_gateway->token_billing == 'optin') ? 'checked' : '' }} />
<span class="ml-1 cursor-pointer">{{ ctrans('texts.no') }}</span>
</label>
</dd>
</div>
<div class="bg-white px-4 py-5 flex justify-end">
<form class="payment-form" method="POST" action="https://merchant.com/successUrl">
@if(app()->environment() == 'production')
<script async src="https://cdn.checkout.com/js/checkout.js"></script>
@else
<script async src="https://cdn.checkout.com/sandbox/js/checkout.js"></script>
@endif
</form>
</div>
@endisset
</div>
</div>
</div>
</div>
@endsection @endsection

View File

@ -0,0 +1,13 @@
<div class="bg-white px-4 py-5 flex justify-end">
<button
@isset($form) form="{{ $form }}" @endisset
type="{{ $type ?? 'button' }}"
id="{{ $id ?? 'pay-now' }}"
class="button button-primary bg-primary">
<svg class="animate-spin h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<span>{{ $slot ?? ctrans('texts.pay_now') }}</span>
</button>
</div>

View File

@ -0,0 +1,17 @@
@unless(isset($show_save) && $show_save == false)
<div class="{{ ($gateway->token_billing == 'optin' || $gateway->token_billing == 'optout') ? 'sm:grid' : 'hidden' }} px-4 py-5 sm:grid-cols-3 sm:gap-4 sm:px-6" id="save-card--container">
<dt class="text-sm leading-5 font-medium text-gray-500">
{{ ctrans('texts.token_billing_checkbox') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<label class="mr-4">
<input type="radio" class="form-radio cursor-pointer" name="token-billing-checkbox" id="proxy_is_default" value="true" {{ ($gateway->token_billing == 'always' || $gateway->token_billing == 'optout') ? 'checked' : '' }} />
<span class="ml-1 cursor-pointer">{{ ctrans('texts.yes') }}</span>
</label>
<label>
<input type="radio" class="form-radio cursor-pointer" name="token-billing-checkbox" id="proxy_is_default" value="false" {{ ($gateway->token_billing == 'off' || $gateway->token_billing == 'optin') ? 'checked' : '' }} />
<span class="ml-1 cursor-pointer">{{ ctrans('texts.no') }}</span>
</label>
</dd>
</div>
@endunless

View File

@ -1,127 +1,75 @@
@extends('portal.ninja2020.layout.app') @extends('portal.ninja2020.layout.payments', ['gateway_title' => 'ACH (Stripe)', 'card_title' => 'ACH (Stripe)'])
@section('meta_title', ctrans('texts.ach'))
@push('head') @section('gateway_head')
<meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}"> <meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}">
@endpush @endsection
@section('gateway_content')
@if(session()->has('ach_error'))
<div class="alert alert-failure mb-4">
<p>{{ session('ach_error') }}</p>
</div>
@endif
@section('body')
<form action="{{ route('client.payment_methods.store', ['method' => App\Models\GatewayType::BANK_TRANSFER]) }}" method="post" id="server_response"> <form action="{{ route('client.payment_methods.store', ['method' => App\Models\GatewayType::BANK_TRANSFER]) }}" method="post" id="server_response">
@csrf @csrf
<input type="hidden" name="company_gateway_id" value="{{ $gateway->id }}"> <input type="hidden" name="company_gateway_id" value="{{ $gateway->id }}">
<input type="hidden" name="gateway_type_id" value="2"> <input type="hidden" name="gateway_type_id" value="2">
<input type="hidden" name="gateway_response" id="gateway_response"> <input type="hidden" name="gateway_response" id="gateway_response">
<input type="hidden" name="is_default" id="is_default"> <input type="hidden" name="is_default" id="is_default">
</form> </form>
<div class="container mx-auto">
<div class="grid grid-cols-6 gap-4"> <div class="alert alert-failure mb-4" hidden id="errors"></div>
<div class="col-span-6 md:col-start-2 md:col-span-4">
<div class="alert alert-failure mb-4" hidden id="errors"></div> @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.account_holder_type')])
@if(session()->has('ach_error')) <span class="flex items-center mr-4">
<div class="alert alert-failure mb-4"> <input class="form-radio mr-2" type="radio" value="individual" name="account-holder-type" checked>
<p>{{ session('ach_error') }}</p> <span>{{ __('texts.individual_account') }}</span>
</div> </span>
@endif <span class="flex items-center">
<div class="bg-white shadow overflow-hidden sm:rounded-lg"> <input class="form-radio mr-2" type="radio" value="company" name="account-holder-type">
<div class="px-4 py-5 border-b border-gray-200 sm:px-6"> <span>{{ __('texts.company_account') }}</span>
<h3 class="text-lg leading-6 font-medium text-gray-900"> </span>
{{ ctrans('texts.ach') }} @endcomponent
</h3>
<p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500"> @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.account_holder_name')])
{{ ctrans('texts.authorize_for_future_use') }}. {{ ctrans('texts.ach_verification_delay_help') }} <input class="input w-full" id="account-holder-name" type="text" placeholder="{{ ctrans('texts.name') }}" required>
</p> @endcomponent
</div>
<div> @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.country')])
<dl> <select name="countries" id="country" class="form-select input w-full" required>
<form action="#" method="post" id="token-form"> @foreach($countries as $country)
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center"> <option value="{{ $country->iso_3166_2 }}">{{ $country->iso_3166_2 }} ({{ $country->name }})</option>
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4"> @endforeach
{{ ctrans('texts.account_holder_type') }} </select>
</dt> @endcomponent
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2 flex">
<span class="flex items-center mr-4"> @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.currency')])
<input class="form-radio mr-2" type="radio" value="individual" name="account-holder-type" checked> <select name="currencies" id="currency" class="form-select input w-full">
<span>{{ __('texts.individual_account') }}</span> @foreach($currencies as $currency)
</span> <option value="{{ $currency->code }}">{{ $currency->code }} ({{ $currency->name }})</option>
<span class="flex items-center"> @endforeach
<input class="form-radio mr-2" type="radio" value="company" name="account-holder-type"> </select>
<span>{{ __('texts.company_account') }}</span> @endcomponent
</span>
</dd> @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.routing_number')])
</div> <input class="input w-full" id="routing-number" type="text" required>
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex-col md:flex-row items-center"> @endcomponent
<dt class="text-sm leading-5 font-medium text-gray-500">
{{ ctrans('texts.account_holder_name') }} @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.account_number')])
</dt> <input class="input w-full" id="account-number" type="text" required>
<dd class="text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2"> @endcomponent
<input class="input w-full" id="account-holder-name" type="text" placeholder="{{ ctrans('texts.name') }}" required>
</dd> @component('portal.ninja2020.components.general.card-element-single')
</div> <input type="checkbox" class="form-checkbox mr-1" id="accept-terms" required>
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex-col md:flex-row items-center"> <label for="accept-terms" class="cursor-pointer">{{ ctrans('texts.ach_authorization', ['company' => auth()->user()->company->present()->name, 'email' => auth()->user()->company->email]) }}</label>
<dt class="text-sm leading-5 font-medium text-gray-500"> @endcomponent
{{ ctrans('texts.country') }}
</dt> @include('portal.ninja2020.gateways.includes.pay_now', ['id' => 'save-button'])
<dd class="text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<select name="countries" id="country" class="form-select input w-full" required>
@foreach($countries as $country)
<option value="{{ $country->iso_3166_2 }}">{{ $country->iso_3166_2 }} ({{ $country->name }})</option>
@endforeach
</select>
</dd>
</div>
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex-col md:flex-row items-center">
<dt class="text-sm leading-5 font-medium text-gray-500">
{{ ctrans('texts.currency') }}
</dt>
<dd class="text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<select name="currencies" id="currency" class="form-select input w-full">
@foreach($currencies as $currency)
<option value="{{ $currency->code }}">{{ $currency->code }} ({{ $currency->name }})</option>
@endforeach
</select>
</dd>
</div>
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex-col md:flex-row items-center">
<dt class="text-sm leading-5 font-medium text-gray-500">
{{ ctrans('texts.routing_number') }}
</dt>
<dd class="text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<input class="input w-full" id="routing-number" type="text" required>
</dd>
</div>
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex-col md:flex-row items-center">
<dt class="text-sm leading-5 font-medium text-gray-500">
{{ ctrans('texts.account_number') }}
</dt>
<dd class="text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<input class="input w-full" id="account-number" type="text" required>
</dd>
</div>
<div class="bg-gray-50 px-4 py-5 sm:grid sm:px-6 flex-col md:flex-row items-center">
<span class="text-sm leading-5 font-medium text-gray-500">
<input type="checkbox" class="form-checkbox mr-1" id="accept-terms" required>
<label for="accept-terms" class="cursor-pointer">{{ ctrans('texts.ach_authorization', ['company' => auth()->user()->company->present()->name, 'email' => auth()->user()->company->email]) }}</label>
</span>
</div>
<div class="bg-white px-4 py-5 flex justify-end">
<button type="submit" class="button button-primary bg-primary" id="save-button">
<svg class="animate-spin h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<span>{{ __('texts.save') }}</span>
</button>
</div>
</form>
</dl>
</div>
</div>
</div>
</div>
</div>
@endsection @endsection
@push('footer') @section('gateway_footer')
<script src="https://js.stripe.com/v3/"></script> <script src="https://js.stripe.com/v3/"></script>
<script src="{{ asset('js/clients/payment_methods/authorize-ach.js') }}"></script> <script src="{{ asset('js/clients/payments/stripe-ach.js') }}"></script>
@endpush @endsection

View File

@ -1,69 +1,38 @@
@extends('portal.ninja2020.layout.app') @extends('portal.ninja2020.layout.payments', ['gateway_title' => 'ACH (Stripe)', 'card_title' => 'ACH (Stripe)'])
@section('meta_title', ctrans('texts.ach'))
@section('body') @section('gateway_content')
@if($token) @if($token)
<div class="alert alert-failure mb-4" hidden id="errors"></div>
@include('portal.ninja2020.gateways.includes.payment_details')
<form action="{{ route('client.payments.response') }}" method="post" id="server-response"> <form action="{{ route('client.payments.response') }}" method="post" id="server-response">
@csrf @csrf
@foreach($invoices as $invoice)
<input type="hidden" name="hashed_ids[]" value="{{ $invoice->hashed_id }}">
@endforeach
<input type="hidden" name="company_gateway_id" value="{{ $gateway->getCompanyGatewayId() }}"> <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="payment_method_id" value="{{ $payment_method_id }}">
<input type="hidden" name="source" value="{{ $token->meta->id }}"> <input type="hidden" name="source" value="{{ $token->token }}">
<input type="hidden" name="amount" value="{{ $amount }}"> <input type="hidden" name="amount" value="{{ $amount }}">
<input type="hidden" name="currency" value="{{ $currency }}"> <input type="hidden" name="currency" value="{{ $currency }}">
<input type="hidden" name="customer" value="{{ $customer->id }}"> <input type="hidden" name="customer" value="{{ $customer->id }}">
</form> </form>
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_type')])
{{ ctrans('texts.ach') }} ({{ ctrans('texts.bank_transfer') }}) (**** {{ $token->meta->last4 }})
@endcomponent
@else
@component('portal.ninja2020.components.general.card-element-single', ['title' => 'ACH', 'show_title' => false])
<span>{{ ctrans('texts.bank_account_not_linked') }}</span>
<a class="button button-link text-primary" href="{{ route('client.payment_methods.index') }}">{{ ctrans('texts.add_payment_method') }}</a>
@endcomponent
@endif @endif
<div class="container mx-auto"> @include('portal.ninja2020.gateways.includes.pay_now')
<div class="grid grid-cols-6 gap-4"> @endsection
<div class="col-span-6 md:col-start-2 md:col-span-4">
<div class="alert alert-failure mb-4" hidden id="errors"></div> @push('footer')
<div class="bg-white shadow overflow-hidden sm:rounded-lg"> <script>
<div class="px-4 py-5 border-b border-gray-200 sm:px-6"> document.getElementById('pay-now').addEventListener('click', function() {
<h3 class="text-lg leading-6 font-medium text-gray-900"> document.getElementById('server-response').submit();
{{ ctrans('texts.pay_now') }} });
</h3> </script>
<p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500"> @endpush
{{ ctrans('texts.complete_your_payment') }}
</p>
</div>
<div>
@if($token)
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center">
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4">
{{ ctrans('texts.payment_type') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
{{ ctrans('texts.ach') }} ({{ ctrans('texts.bank_transfer') }}) (****{{ $token->meta->last4 }})
</dd>
</div>
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center">
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4">
{{ ctrans('texts.amount') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<span class="font-bold">{{ App\Utils\Number::formatMoney($amount, $client) }}</span>
</dd>
</div>
<div class="bg-gray-50 px-4 py-5 flex justify-end">
<button type="button" id="pay-now" class="button button-primary bg-primary" onclick="document.getElementById('server-response').submit()">
{{ ctrans('texts.pay_now') }}
</button>
</div>
@else
<div class="bg-gray-50 px-4 py-5 sm:px-6 flex items-center">
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<span>{{ ctrans('texts.bank_account_not_linked') }}</span>
<a class="button button-link text-primary" href="{{ route('client.payment_methods.index') }}">{{ ctrans('texts.add_payment_method') }}</a>
</dd>
</div>
@endif
</div>
</div>
</div>
</div>
</div>
@endsection

View File

@ -1,54 +1,25 @@
@extends('portal.ninja2020.layout.app') @extends('portal.ninja2020.layout.payments', ['gateway_title' => 'ACH (Verification)', 'card_title' => 'ACH (Verification)'])
@section('meta_title', ctrans('texts.verification'))
@section('body') @section('gateway_content')
<div class="container mx-auto"> @if(session()->has('error'))
<div class="grid grid-cols-6 gap-4"> <div class="alert alert-failure mb-4">{{ session('error') }}</div>
<div class="col-span-6 md:col-start-2 md:col-span-4"> @endif
@if(session()->has('error'))
<div class="alert alert-failure mb-4">{{ session('error') }}</div>
@endif
<div class="bg-white shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 border-b border-gray-200 sm:px-6">
<h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.verification') }}
</h3>
<p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500">
{{ ctrans('texts.complete_your_bank_account_verification') }} ({{ ctrans('texts.ach') }}/{{ $token->meta->last4 }})
</p>
<a href="#" class="button-link text-primary text-sm">{{ __('texts.learn_more') }}</a>
</div>
<div>
<form method="post">
@csrf
<input type="hidden" name="customer" value="{{ $token->gateway_customer_reference }}">
<input type="hidden" name="source" value="{{ $token->meta->id }}">
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center"> <form method="POST">
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4"> @csrf
#1 {{ ctrans('texts.amount') }} <input type="hidden" name="customer" value="{{ $token->gateway_customer_reference }}">
</dt> <input type="hidden" name="source" value="{{ $token->token }}">
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<input type="text" name="transactions[]" class="w-full input" required> @component('portal.ninja2020.components.general.card-element', ['title' => '#1 ' . ctrans('texts.amount')])
</dd> <input type="text" name="transactions[]" class="w-full input" required>
</div> @endcomponent
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center">
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4"> @component('portal.ninja2020.components.general.card-element', ['title' => '#2 ' . ctrans('texts.amount')])
#2 {{ ctrans('texts.amount') }} <input type="text" name="transactions[]" class="w-full input" required>
</dt> @endcomponent
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<input type="text" name="transactions[]" class="w-full input" required> @component('portal.ninja2020.gateways.includes.pay_now', ['type' => 'submit'])
</dd> {{ ctrans('texts.complete_verification')}}
</div> @endcomponent
<div class="bg-gray-50 px-4 py-5 flex justify-end"> </form>
<button id="pay-now" class="button button-primary bg-primary">
{{ ctrans('texts.complete_verification') }}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection @endsection

View File

@ -1,52 +0,0 @@
@extends('portal.ninja2020.layout.app')
@section('meta_title', ctrans('texts.add_credit_card'))
@push('head')
<meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}">
@endpush
@section('body')
<form action="{{ route('client.payment_methods.store', ['method' => App\Models\GatewayType::CREDIT_CARD]) }}" method="post" id="server_response">
@csrf
<input type="hidden" name="company_gateway_id" value="{{ $gateway->gateway_id }}">
<input type="hidden" name="payment_method_id" value="1">
<input type="hidden" name="gateway_response" id="gateway_response">
<input type="hidden" name="is_default" id="is_default">
</form>
<div class="container mx-auto">
<div class="grid grid-cols-6 gap-4">
<div class="col-span-6 md:col-start-2 md:col-span-4">
<div class="alert alert-failure mb-4" hidden id="errors"></div>
<div class="bg-white shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 border-b border-gray-200 sm:px-6">
<h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.add_credit_card') }}
</h3>
<p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500">
{{ ctrans('texts.authorize_for_future_use') }}
</p>
</div>
<div>
@include('portal.ninja2020.gateways.stripe.includes.card_widget')
<div class="bg-white px-4 py-5 flex justify-end">
<button type="button" id="card-button" data-secret="{{ $intent->client_secret }}" class="button button-primary bg-primary">
<svg class="animate-spin h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<span>{{ __('texts.save') }}</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
@push('footer')
<script src="https://js.stripe.com/v3/"></script>
<script src="{{ asset('js/clients/payment_methods/authorize-stripe-card.js') }}"></script>
@endpush

View File

@ -1,61 +1,25 @@
@extends('portal.ninja2020.layout.app') @extends('portal.ninja2020.layout.payments', ['gateway_title' => 'Alipay (Stripe)', 'card_title' => 'Alipay (Stripe)'])
@section('meta_title', ctrans('texts.alipay'))
@push('head') @section('gateway_head')
<meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}"> <meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}">
<meta name="return-url" content="{{ $return_url }}"> <meta name="return-url" content="{{ $return_url }}">
<meta name="currency" content="{{ $currency }}"> <meta name="currency" content="{{ $currency }}">
<meta name="amount" content="{{ $stripe_amount }}"> <meta name="amount" content="{{ $stripe_amount }}">
@endpush @endsection
@section('body') @section('gateway_content')
<div class="container mx-auto"> <div class="alert alert-failure mb-4" hidden id="errors"></div>
<div class="grid grid-cols-6 gap-4">
<div class="col-span-6 md:col-start-2 md:col-span-4"> @include('portal.ninja2020.gateways.includes.payment_details')
<div class="alert alert-failure mb-4" hidden id="errors"></div>
<div class="bg-white shadow overflow-hidden sm:rounded-lg"> @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_type')])
<div class="px-4 py-5 border-b border-gray-200 sm:px-6"> {{ ctrans('texts.alipay') }}
<h3 class="text-lg leading-6 font-medium text-gray-900"> @endcomponent
{{ ctrans('texts.pay_now') }}
</h3> @include('portal.ninja2020.gateways.includes.pay_now')
<p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500">
{{ ctrans('texts.complete_your_payment') }}
</p>
</div>
<form action="#" method="POST" id="pay-now">
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center">
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4">
{{ ctrans('texts.payment_type') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
{{ ctrans('texts.alipay') }}
</dd>
</div>
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center">
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4">
{{ ctrans('texts.amount') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<span class="font-bold">{{ App\Utils\Number::formatMoney($amount, $client) }}</span>
</dd>
</div>
<div class="bg-gray-50 px-4 py-5 flex justify-end">
<button class="button button-primary bg-primary" id="pay-now-button">
<svg class="animate-spin h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<span>{{ __('texts.save') }}</span>
</button>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection @endsection
@push('footer') @push('footer')
<script src="https://js.stripe.com/v3/"></script> <script src="https://js.stripe.com/v3/"></script>
<script src="{{ asset('js/clients/payments/alipay.js') }}"></script> <script src="{{ asset('js/clients/payments/stripe-alipay.js') }}"></script>
@endpush @endpush

View File

@ -1,65 +0,0 @@
@extends('portal.ninja2020.layout.app')
@section('meta_title', ctrans('texts.pay_now'))
@push('head')
<meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}">
<meta name="using-token" content="{{ boolval($token) }}">
@endpush
@section('body')
<form action="{{ route('client.payments.response') }}" method="post" id="server-response">
@csrf
<input type="hidden" name="gateway_response">
<input type="hidden" name="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 }}">
</form>
<div class="container mx-auto">
<div class="grid grid-cols-6 gap-4">
<div class="col-span-6 md:col-start-2 md:col-span-4">
<div class="alert alert-failure mb-4" hidden id="errors"></div>
<div class="bg-white shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 border-b border-gray-200 sm:px-6">
<h3 class="text-lg leading-6 font-medium text-gray-900">
{{ ctrans('texts.pay_now') }}
</h3>
<p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500">
{{ ctrans('texts.complete_your_payment') }}
</p>
</div>
<div>
<dl>
@include('portal.ninja2020.gateways.includes.payment_details')
@if((int)$total['amount_with_fee'] == 0)
@include('portal.ninja2020.gateways.stripe.includes.pay_with_credit')
@elseif($token)
@include('portal.ninja2020.gateways.stripe.includes.pay_with_token')
@else
@include('portal.ninja2020.gateways.stripe.includes.card_widget')
<div class="bg-white px-4 py-5 flex justify-end">
<button type="button" id="pay-now" data-secret="{{ $intent->client_secret }}" class="button button-primary bg-primary">
<svg class="animate-spin h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<span>{{ __('texts.pay_now') }}</span>
</button>
</div>
@endif
</dl>
</div>
</div>
</div>
</div>
</div>
@endsection
@push('footer')
<script src="https://js.stripe.com/v3/"></script>
<script src="{{ asset('js/clients/payments/process.js') }}"></script>
@endpush

View File

@ -0,0 +1,35 @@
@extends('portal.ninja2020.layout.payments', ['gateway_title' => 'Stripe (Credit card)', 'card_title' => 'Stripe (Credit card)'])
@section('gateway_head')
<meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}">
<meta name="stripe-secret" content="{{ $intent->client_secret }}">
<meta name="only-authorization" content="true">
<meta name="stripe-token" content="">
@endsection
@section('gateway_content')
<form action="{{ route('client.payment_methods.store', ['method' => App\Models\GatewayType::CREDIT_CARD]) }}" method="post" id="server_response">
@csrf
<input type="hidden" name="company_gateway_id" value="{{ $gateway->gateway_id }}">
<input type="hidden" name="payment_method_id" value="1">
<input type="hidden" name="gateway_response" id="gateway_response">
<input type="hidden" name="is_default" id="is_default">
</form>
<div class="alert alert-failure mb-4" hidden id="errors"></div>
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.method')])
{{ ctrans('texts.credit_card') }} (Stripe)
@endcomponent
@include('portal.ninja2020.gateways.stripe.includes.card_widget')
@component('portal.ninja2020.gateways.includes.pay_now', ['id' => 'authorize-card'])
{{ __('texts.save') }}
@endcomponent
@endsection
@section('gateway_footer')
<script src="https://js.stripe.com/v3/"></script>
<script src="{{ asset('js/clients/payments/stripe-credit-card.js') }}"></script>
@endsection

View File

@ -0,0 +1,41 @@
@extends('portal.ninja2020.layout.payments', ['gateway_title' => 'Stripe (Credit card)', 'card_title' => 'Stripe (Credit card)'])
@section('gateway_head')
<meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}">
<meta name="stripe-secret" content="{{ $intent->client_secret }}">
<meta name="stripe-token" content="{{ optional($token)->token }}">
<meta name="only-authorization" content="">
@endsection
@section('gateway_content')
<form action="{{ route('client.payments.response') }}" method="post" id="server-response">
@csrf
<input type="hidden" name="gateway_response">
<input type="hidden" name="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 }}">
</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') }} (Stripe)
@endcomponent
@include('portal.ninja2020.gateways.includes.payment_details')
@if($token)
@include('portal.ninja2020.gateways.stripe.includes.pay_with_token')
@include('portal.ninja2020.gateways.includes.pay_now', ['id' => 'pay-now-with-token'])
@else
@include('portal.ninja2020.gateways.stripe.includes.card_widget')
@include('portal.ninja2020.gateways.includes.pay_now')
@endif
@endsection
@section('gateway_footer')
<script src="https://js.stripe.com/v3/"></script>
<script src="{{ asset('js/clients/payments/stripe-credit-card.js') }}"></script>
@endsection

View File

@ -1,39 +1,13 @@
@unless(isset($show_name) && $show_name == false) @unless(isset($show_name) && $show_name == false)
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center"> @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.name')])
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4"> <input class="input w-full" id="cardholder-name" type="text" placeholder="{{ ctrans('texts.name') }}">
{{ ctrans('texts.name') }} @endcomponent
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<input class="input w-full" id="cardholder-name" type="text" placeholder="{{ ctrans('texts.name') }}">
</dd>
</div>
@endunless @endunless
@unless(isset($show_card_element) && $show_card_element == false) @unless(isset($show_card_element) && $show_card_element == false)
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"> @component('portal.ninja2020.components.general.card-element-single')
<dt class="text-sm leading-5 font-medium text-gray-500"> <div id="card-element"></div>
{{ ctrans('texts.credit_card') }} @endcomponent
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<div id="card-element"></div>
</dd>
</div>
@endunless @endunless
@unless(isset($show_save) && $show_save == false) @include('portal.ninja2020.gateways.includes.save_card')
<div class="{{ ($gateway->token_billing == 'optin' || $gateway->token_billing == 'optout') ? 'sm:grid' : 'hidden' }} bg-gray-50 px-4 py-5 sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm leading-5 font-medium text-gray-500">
{{ ctrans('texts.token_billing_checkbox') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<label class="mr-4">
<input type="radio" class="form-radio cursor-pointer" name="token-billing-checkbox" id="proxy_is_default" value="true" {{ ($gateway->token_billing == 'always' || $gateway->token_billing == 'optout') ? 'checked' : '' }} />
<span class="ml-1 cursor-pointer">{{ ctrans('texts.yes') }}</span>
</label>
<label>
<input type="radio" class="form-radio cursor-pointer" name="token-billing-checkbox" id="proxy_is_default" value="false" {{ ($gateway->token_billing == 'off' || $gateway->token_billing == 'optin') ? 'checked' : '' }} />
<span class="ml-1 cursor-pointer">{{ ctrans('texts.no') }}</span>
</label>
</dd>
</div>
@endunless

View File

@ -3,6 +3,6 @@
<input type="hidden" name="payment_hash" value="{{ $payment_hash }}"> <input type="hidden" name="payment_hash" value="{{ $payment_hash }}">
</form> </form>
<div class="bg-white px-4 py-5 flex justify-end"> @component('portal.ninja2020.gateways.includes.pay_now', ['id' => 'pay-with-credit', 'form' => 'credit-payment'])
<button form="credit-payment" class="button button-primary bg-primary inline-flex items-center">Pay with credit</button> {{ ctrans('texts.pay_with_credit') }}
</div> @endcomponent

View File

@ -1,12 +1,18 @@
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center"> {{-- <div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center">
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4"> <dt class="text-sm leading-5 font-medium text-gray-500 mr-4">
{{ ctrans('texts.credit_card') }} {{ ctrans('texts.credit_card') }}
</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">
{{ strtoupper($token->meta->brand) }} - **** {{ $token->meta->last4 }} {{ strtoupper($token->meta->brand) }} - **** {{ $token->meta->last4 }}
</dd> </dd>
</div> </div> --}}
<div class="bg-white px-4 py-5 flex justify-end">
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.credit_card')])
{{ strtoupper($token->meta->brand) }} - **** {{ $token->meta->last4 }}
@endcomponent
{{-- <div class="bg-white px-4 py-5 flex justify-end">
<button type="button" data-secret="{{ $intent->client_secret }}" data-token="{{ $token->token }}" id="pay-now-with-token" class="button button-primary bg-primary inline-flex items-center"> <button type="button" data-secret="{{ $intent->client_secret }}" data-token="{{ $token->token }}" id="pay-now-with-token" class="button button-primary bg-primary inline-flex items-center">
<svg class="animate-spin h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> <svg class="animate-spin h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle> <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
@ -14,4 +20,4 @@
</svg> </svg>
<span>{{ __('texts.pay_now') }}</span> <span>{{ __('texts.pay_now') }}</span>
</button> </button>
</div> </div> --}}

View File

@ -1,61 +1,25 @@
@extends('portal.ninja2020.layout.app') @extends('portal.ninja2020.layout.payments', ['gateway_title' => 'SOFORT (Stripe)', 'card_title' => 'SOFORT (Stripe)'])
@section('meta_title', ctrans('texts.sofort'))
@push('head') @section('gateway_head')
<meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}"> <meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}">
<meta name="return-url" content="{{ $return_url }}"> <meta name="return-url" content="{{ $return_url }}">
<meta name="amount" content="{{ $stripe_amount }}"> <meta name="amount" content="{{ $stripe_amount }}">
<meta name="country" content="{{ $country }}"> <meta name="country" content="{{ $country }}">
@endpush @endsection
@section('body') @section('gateway_content')
<div class="container mx-auto"> <div class="alert alert-failure mb-4" hidden id="errors"></div>
<div class="grid grid-cols-6 gap-4">
<div class="col-span-6 md:col-start-2 md:col-span-4"> @include('portal.ninja2020.gateways.includes.payment_details')
<div class="alert alert-failure mb-4" hidden id="errors"></div>
<div class="bg-white shadow overflow-hidden sm:rounded-lg"> @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_type')])
<div class="px-4 py-5 border-b border-gray-200 sm:px-6"> {{ ctrans('texts.sofort') }} ({{ ctrans('texts.bank_transfer') }})
<h3 class="text-lg leading-6 font-medium text-gray-900"> @endcomponent
{{ ctrans('texts.pay_now') }}
</h3> @include('portal.ninja2020.gateways.includes.pay_now')
<p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500">
{{ ctrans('texts.complete_your_payment') }}
</p>
</div>
<form action="#" method="POST" id="pay-now">
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center">
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4">
{{ ctrans('texts.payment_type') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
{{ ctrans('texts.sofort') }} ({{ ctrans('texts.bank_transfer') }})
</dd>
</div>
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center">
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4">
{{ ctrans('texts.amount') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<span class="font-bold">{{ App\Utils\Number::formatMoney($amount, $client) }}</span>
</dd>
</div>
<div class="bg-gray-50 px-4 py-5 flex justify-end" id="pay-now-button">
<button class="button button-primary bg-primary">
<svg class="animate-spin h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<span>{{ __('texts.save') }}</span>
</button>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection @endsection
@push('footer') @push('footer')
<script src="https://js.stripe.com/v3/"></script> <script src="https://js.stripe.com/v3/"></script>
<script src="{{ asset('js/clients/payments/sofort.js') }}"></script> <script src="{{ asset('js/clients/payments/stripe-sofort.js') }}"></script>
@endpush @endpush

View File

@ -0,0 +1,37 @@
@extends('portal.ninja2020.layout.app')
@isset($gateway_title)
@section('meta_title', $gateway_title)
@else
@section('meta_title', ctrans('texts.pay_now'))
@endisset
@push('head')
@yield('gateway_head')
@endpush
@section('body')
<div class="container mx-auto grid grid-cols-12">
<div class="col-span-12 lg:col-span-6 lg:col-start-4 overflow-hidden bg-white shadow rounded-lg">
<div class="px-4 py-5 border-b border-gray-200 sm:px-6">
@isset($card_title)
<h3 class="text-lg font-medium leading-6 text-gray-900">
{{ $card_title }}
</h3>
@endisset
@isset($card_description)
<p class="max-w-2xl mt-1 text-sm leading-5 text-gray-500">
{{ $card_description }}
</p>
@endisset
</div>
<div>
@yield('gateway_content')
</div>
</div>
</div>
@endsection
@push('footer')
@yield('gateway_footer')
@endpush

View File

@ -31,7 +31,9 @@
{{ ctrans('texts.transaction_reference') }} {{ ctrans('texts.transaction_reference') }}
</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">
{{ $payment->transaction_reference }} <span class="break-all">
{{ $payment->transaction_reference }}
</span>
</dd> </dd>
</div> </div>
@endif @endif

20
webpack.mix.js vendored
View File

@ -2,10 +2,6 @@ const mix = require("laravel-mix");
const tailwindcss = require("tailwindcss"); const tailwindcss = require("tailwindcss");
mix.js("resources/js/app.js", "public/js") mix.js("resources/js/app.js", "public/js")
.js(
"resources/js/clients/payment_methods/authorize-stripe-card.js",
"public/js/clients/payment_methods/authorize-stripe-card.js"
)
.js( .js(
"resources/js/clients/payment_methods/authorize-authorize-card.js", "resources/js/clients/payment_methods/authorize-authorize-card.js",
"public/js/clients/payment_methods/authorize-authorize-card.js" "public/js/clients/payment_methods/authorize-authorize-card.js"
@ -15,8 +11,8 @@ mix.js("resources/js/app.js", "public/js")
"public/js/clients/payments/authorize-credit-card-payment.js" "public/js/clients/payments/authorize-credit-card-payment.js"
) )
.js( .js(
"resources/js/clients/payment_methods/authorize-ach.js", "resources/js/clients/payments/stripe-ach.js",
"public/js/clients/payment_methods/authorize-ach.js" "public/js/clients/payments/stripe-ach.js"
) )
.js( .js(
"resources/js/clients/invoices/action-selectors.js", "resources/js/clients/invoices/action-selectors.js",
@ -27,12 +23,12 @@ mix.js("resources/js/app.js", "public/js")
"public/js/clients/invoices/payment.js" "public/js/clients/invoices/payment.js"
) )
.js( .js(
"resources/js/clients/payments/sofort.js", "resources/js/clients/payments/stripe-sofort.js",
"public/js/clients/payments/sofort.js" "public/js/clients/payments/stripe-sofort.js"
) )
.js( .js(
"resources/js/clients/payments/alipay.js", "resources/js/clients/payments/stripe-alipay.js",
"public/js/clients/payments/alipay.js" "public/js/clients/payments/stripe-alipay.js"
) )
.js( .js(
"resources/js/clients/payments/checkout.com.js", "resources/js/clients/payments/checkout.com.js",
@ -47,8 +43,8 @@ mix.js("resources/js/app.js", "public/js")
"public/js/clients/quotes/approve.js" "public/js/clients/quotes/approve.js"
) )
.js( .js(
"resources/js/clients/payments/process.js", "resources/js/clients/payments/stripe-credit-card.js",
"public/js/clients/payments/process.js" "public/js/clients/payments/stripe-credit-card.js"
) )
.js( .js(
"resources/js/setup/setup.js", "resources/js/setup/setup.js",