diff --git a/app/Http/Controllers/ClientPortal/TempRouteController.php b/app/Http/Controllers/ClientPortal/TempRouteController.php index d29a2c432c19..3ae858a9e1a7 100644 --- a/app/Http/Controllers/ClientPortal/TempRouteController.php +++ b/app/Http/Controllers/ClientPortal/TempRouteController.php @@ -26,9 +26,8 @@ class TempRouteController extends Controller public function index(string $hash) { $data = []; - $data['html'] = Cache::get($hash); + $data['html'] = Cache::get($hash); return view('pdf.html', $data); - } } diff --git a/app/Http/Controllers/PreviewController.php b/app/Http/Controllers/PreviewController.php index c45534fd427a..155d961a247c 100644 --- a/app/Http/Controllers/PreviewController.php +++ b/app/Http/Controllers/PreviewController.php @@ -199,9 +199,9 @@ class PreviewController extends BaseController ->design($design) ->build(); - if (config('ninja.phantomjs_pdf_generation')) { - return (new Phantom)->convertHtmlToPdf($maker->getCompiledHTML(true)); - } + if (config('ninja.phantomjs_pdf_generation')) { + return (new Phantom)->convertHtmlToPdf($maker->getCompiledHTML(true)); + } $file_path = PreviewPdf::dispatchNow($maker->getCompiledHTML(true), auth()->user()->company()); diff --git a/app/Http/Livewire/Profile/Settings/NameWebsiteLogo.php b/app/Http/Livewire/Profile/Settings/NameWebsiteLogo.php index ea363872a9f0..ca8282b9e67f 100644 --- a/app/Http/Livewire/Profile/Settings/NameWebsiteLogo.php +++ b/app/Http/Livewire/Profile/Settings/NameWebsiteLogo.php @@ -10,12 +10,14 @@ class NameWebsiteLogo extends Component public $name; public $website; + public $phone; public $saved; public $rules = [ 'name' => ['required', 'min:3'], 'website' => ['required', 'url'], + 'phone' => ['required', 'string', 'max:255'], ]; public function mount() @@ -24,6 +26,7 @@ class NameWebsiteLogo extends Component 'profile' => auth()->user('contact')->client, 'name' => auth()->user('contact')->client->present()->name, 'website' => auth()->user('contact')->client->present()->website, + 'phone' => auth()->user('contact')->client->present()->phone, 'saved' => ctrans('texts.save'), ]); } @@ -37,9 +40,11 @@ class NameWebsiteLogo extends Component { $data = $this->validate($this->rules); - $this->profile - ->fill($data) - ->save(); + $this->profile->name = $data['name']; + $this->profile->website = $data['website']; + $this->profile->phone = $data['phone']; + + $this->profile->save(); $this->saved = ctrans('texts.saved_at', ['time' => now()->toTimeString()]); } diff --git a/app/Models/CompanyUser.php b/app/Models/CompanyUser.php index 1bd1a7373869..bb569ac62719 100644 --- a/app/Models/CompanyUser.php +++ b/app/Models/CompanyUser.php @@ -11,7 +11,6 @@ namespace App\Models; -use App\Models\TaxRate; use Illuminate\Database\Eloquent\Relations\Pivot; use Illuminate\Database\Eloquent\SoftDeletes; @@ -58,7 +57,7 @@ class CompanyUser extends Pivot public function tax_rates() { - return $this->hasMany(TaxRate::class,'company_id', 'company_id'); + return $this->hasMany(TaxRate::class, 'company_id', 'company_id'); } public function account() diff --git a/app/PaymentDrivers/Authorize/AuthorizeCreditCard.php b/app/PaymentDrivers/Authorize/AuthorizeCreditCard.php index 1dda822d2182..ae3e12cf6c12 100644 --- a/app/PaymentDrivers/Authorize/AuthorizeCreditCard.php +++ b/app/PaymentDrivers/Authorize/AuthorizeCreditCard.php @@ -166,7 +166,8 @@ class AuthorizeCreditCard $payment_record = []; $payment_record['amount'] = $amount; - $payment_record['payment_type'] = PaymentType::CREDIT_CARD_OTHER;; + $payment_record['payment_type'] = PaymentType::CREDIT_CARD_OTHER; + ; $payment_record['transaction_reference'] = $response->getTransactionResponse()->getTransId(); $payment = $this->authorize->createPayment($payment_record); diff --git a/app/PaymentDrivers/Authorize/AuthorizePaymentMethod.php b/app/PaymentDrivers/Authorize/AuthorizePaymentMethod.php index 8b1ab194a530..189d51d35de6 100644 --- a/app/PaymentDrivers/Authorize/AuthorizePaymentMethod.php +++ b/app/PaymentDrivers/Authorize/AuthorizePaymentMethod.php @@ -13,11 +13,8 @@ namespace App\PaymentDrivers\Authorize; use App\Exceptions\GenericPaymentDriverFailure; -use App\Models\ClientGatewayToken; use App\Models\GatewayType; use App\PaymentDrivers\AuthorizePaymentDriver; -use App\PaymentDrivers\Authorize\AuthorizeCreateCustomer; -use App\PaymentDrivers\Authorize\AuthorizeCreditCard; use net\authorize\api\contract\v1\CreateCustomerPaymentProfileRequest; use net\authorize\api\contract\v1\CustomerAddressType; use net\authorize\api\contract\v1\CustomerPaymentProfileType; @@ -46,19 +43,16 @@ class AuthorizePaymentMethod public function authorizeView() { - if($this->authorize->payment_method instanceof AuthorizeCreditCard){ - + if ($this->authorize->payment_method instanceof AuthorizeCreditCard) { $this->payment_method_id = GatewayType::CREDIT_CARD; return $this->authorizeCreditCard(); - } // case GatewayType::BANK_TRANSFER: // return $this->authorizeBankTransfer(); // break; - } public function authorizeResponseView($request) @@ -116,7 +110,6 @@ class AuthorizePaymentMethod public function createClientGatewayToken($payment_profile, $gateway_customer_reference) { - $data = []; $additonal = []; diff --git a/app/PaymentDrivers/BaseDriver.php b/app/PaymentDrivers/BaseDriver.php index 12c32023e486..6730c1ea947d 100644 --- a/app/PaymentDrivers/BaseDriver.php +++ b/app/PaymentDrivers/BaseDriver.php @@ -31,8 +31,8 @@ use App\Utils\Traits\MakesHash; use App\Utils\Traits\SystemLogTrait; use Checkout\Library\Exceptions\CheckoutHttpException; use Exception; -use Illuminate\Support\Carbon; use Illuminate\Http\Request; +use Illuminate\Support\Carbon; /** * Class BaseDriver. @@ -83,35 +83,43 @@ class BaseDriver extends AbstractPaymentDriver * Authorize a payment method. * * Returns a reusable token for storage for future payments - * + * * @param array $data * @return mixed Return a view for collecting payment method information */ - public function authorizeView(array $data) {} + public function authorizeView(array $data) + { + } /** * The payment authorization response - * - * @param Request $request + * + * @param Request $request * @return mixed Return a response for collecting payment method information */ - public function authorizeResponse(Request $request) {} + public function authorizeResponse(Request $request) + { + } /** * Process a payment - * - * @param array $data + * + * @param array $data * @return mixed Return a view for the payment */ - public function processPaymentView(array $data) {} + public function processPaymentView(array $data) + { + } /** * Process payment response - * + * * @param Request $request * @return mixed Return a response for the payment */ - public function processPaymentResponse(Request $request) {} + public function processPaymentResponse(Request $request) + { + } /** * Executes a refund attempt for a given amount with a transaction_reference. @@ -121,7 +129,9 @@ class BaseDriver extends AbstractPaymentDriver * @param bool $return_client_response Whether the method needs to return a response (otherwise we assume an unattended payment) * @return mixed */ - public function refund(Payment $payment, $amount, $return_client_response = false) {} + public function refund(Payment $payment, $amount, $return_client_response = false) + { + } /** * Process an unattended payment. @@ -130,14 +140,18 @@ class BaseDriver extends AbstractPaymentDriver * @param PaymentHash $payment_hash The Payment hash containing the payment meta data * @return void The payment response */ - public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash){} + public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash) + { + } /** * Set the inbound request payment method type for access. * * @param int $payment_method_id The Payment Method ID */ - public function setPaymentMethod($payment_method_id){} + public function setPaymentMethod($payment_method_id) + { + } /************************** Helper methods *************************************/ @@ -334,9 +348,9 @@ class BaseDriver extends AbstractPaymentDriver /** * Wrapper method for checking if resource is good. - * - * @param mixed $resource - * @return bool + * + * @param mixed $resource + * @return bool */ public function checkRequiredResource($resource): bool { @@ -436,7 +450,7 @@ class BaseDriver extends AbstractPaymentDriver if (Str::startsWith($field, 'billing')) { unset($this->required_fields[$position]); } - } + } if ($this->checkRequiredResource(auth()->user('contact')->client->postal_code)) { $this->required_fields[] = 'postal_code'; diff --git a/app/PaymentDrivers/DriverTemplate.php b/app/PaymentDrivers/DriverTemplate.php index 8044062f9d95..a726bca1ab3b 100644 --- a/app/PaymentDrivers/DriverTemplate.php +++ b/app/PaymentDrivers/DriverTemplate.php @@ -55,19 +55,18 @@ class DriverTemplate extends BaseDriver return $this->payment_method->paymentView($data); //this is your custom implementation from here } - public function processPaymentResponse($request) + public function processPaymentResponse($request) { return $this->payment_method->paymentResponse($request); //this is your custom implementation from here } public function refund(Payment $payment, $amount, $return_client_response = false) { - return $this->payment_method->yourRefundImplementationHere(); //this is your custom implementation from here + return $this->payment_method->yourRefundImplementationHere(); //this is your custom implementation from here } public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash) { return $this->payment_method->yourTokenBillingImplmentation(); //this is your custom implementation from here } - } diff --git a/app/PaymentDrivers/PayPalExpressPaymentDriver.php b/app/PaymentDrivers/PayPalExpressPaymentDriver.php index c05b7d2f7abf..752ebf48c69d 100644 --- a/app/PaymentDrivers/PayPalExpressPaymentDriver.php +++ b/app/PaymentDrivers/PayPalExpressPaymentDriver.php @@ -12,40 +12,28 @@ namespace App\PaymentDrivers; -use App\Events\Payment\PaymentWasCreated; +use App\Exceptions\PaymentFailed; use App\Jobs\Mail\PaymentFailureMailer; use App\Jobs\Util\SystemLogger; -use App\Models\ClientGatewayToken; use App\Models\GatewayType; -use App\Models\Payment; -use App\Models\PaymentHash; +use App\Models\Invoice; use App\Models\PaymentType; use App\Models\SystemLog; -use App\Utils\Ninja; use App\Utils\Traits\MakesHash; -use Exception; use Omnipay\Common\Item; -use stdClass; -class PayPalExpressPaymentDriver extends BasePaymentDriver +use Omnipay\Omnipay; + +class PayPalExpressPaymentDriver extends BaseDriver { use MakesHash; - public $payment_hash; + public $token_billing = false; - public $required_fields = []; + public $can_authorise_credit_card = false; - protected $refundable = true; + private $omnipay_gateway; - protected $token_billing = false; - - protected $can_authorise_credit_card = false; - - protected $customer_reference = ''; - - public function setPaymentMethod($payment_method_id = null) - { - return $this; - } + const SYSTEM_LOG_TYPE = SystemLog::TYPE_PAYPAL; public function gatewayTypes() { @@ -54,131 +42,43 @@ class PayPalExpressPaymentDriver extends BasePaymentDriver ]; } - const SYSTEM_LOG_TYPE = SystemLog::TYPE_PAYPAL; - -public function checkRequirements() + /** + * Initialize Omnipay PayPal_Express gateway. + * + * @return void + */ + private function initializeOmnipayGateway(): void { - if ($this->company_gateway->require_billing_address) { - if ($this->checkRequiredResource(auth()->user('contact')->client->address1)) { - $this->required_fields[] = 'billing_address1'; - } + $this->omnipay_gateway = Omnipay::create( + $this->company_gateway->gateway->provider + ); - if ($this->checkRequiredResource(auth()->user('contact')->client->address2)) { - $this->required_fields[] = 'billing_address2'; - } + $this->omnipay_gateway->initialize((array) $this->company_gateway->getConfig()); + } - if ($this->checkRequiredResource(auth()->user('contact')->client->city)) { - $this->required_fields[] = 'billing_city'; - } - - if ($this->checkRequiredResource(auth()->user('contact')->client->state)) { - $this->required_fields[] = 'billing_state'; - } - - if ($this->checkRequiredResource(auth()->user('contact')->client->postal_code)) { - $this->required_fields[] = 'billing_postal_code'; - } - - if ($this->checkRequiredResource(auth()->user('contact')->client->country_id)) { - $this->required_fields[] = 'billing_country'; - } - } - - if ($this->company_gateway->require_shipping_address) { - if ($this->checkRequiredResource(auth()->user('contact')->client->shipping_address1)) { - $this->required_fields[] = 'shipping_address1'; - } - - if ($this->checkRequiredResource(auth()->user('contact')->client->shipping_address2)) { - $this->required_fields[] = 'shipping_address2'; - } - - if ($this->checkRequiredResource(auth()->user('contact')->client->shipping_city)) { - $this->required_fields[] = 'shipping_city'; - } - - if ($this->checkRequiredResource(auth()->user('contact')->client->shipping_state)) { - $this->required_fields[] = 'shipping_state'; - } - - if ($this->checkRequiredResource(auth()->user('contact')->client->shipping_postal_code)) { - $this->required_fields[] = 'shipping_postal_code'; - } - - if ($this->checkRequiredResource(auth()->user('contact')->client->shipping_country_id)) { - $this->required_fields[] = 'shipping_country'; - } - } - - if ($this->company_gateway->require_client_name) { - if ($this->checkRequiredResource(auth()->user('contact')->client->name)) { - $this->required_fields[] = 'name'; - } - } - - if ($this->company_gateway->require_client_phone) { - if ($this->checkRequiredResource(auth()->user('contact')->client->phone)) { - $this->required_fields[] = 'phone'; - } - } - - if ($this->company_gateway->require_contact_email) { - if ($this->checkRequiredResource(auth()->user('contact')->email)) { - $this->required_fields[] = 'contact_email'; - } - } - - if ($this->company_gateway->require_contact_name) { - if ($this->checkRequiredResource(auth()->user('contact')->first_name)) { - $this->required_fields[] = 'contact_first_name'; - } - - if ($this->checkRequiredResource(auth()->user('contact')->last_name)) { - $this->required_fields[] = 'contact_last_name'; - } - } - - if ($this->company_gateway->require_postal_code) { - // In case "require_postal_code" is true, we don't need billing address. - - foreach ($this->required_fields as $position => $field) { - if (Str::startsWith($field, 'billing')) { - unset($this->required_fields[$position]); - } - } - - if ($this->checkRequiredResource(auth()->user('contact')->client->postal_code)) { - $this->required_fields[] = 'postal_code'; - } - } + public function setPaymentMethod($payment_method_id) + { + // PayPal doesn't have multiple ways of paying. + // There's just one, off-site redirect. return $this; } - /** - * Wrapper method for checking if resource is good. - * - * @param mixed $resource - * @return bool - */ - public function checkRequiredResource($resource): bool + public function authorizeView($payment_method) { - if (is_null($resource) || empty($resource)) { - return true; - } + // PayPal doesn't support direct authorization. - return false; + return $this; } - /** - * Processes the payment with this gateway. - * - * - * @param array $data variables required to build payment page - * @return void Gateway and payment method specific view - * @throws Exception - */ - public function processPaymentView(array $data) + public function authorizeResponse($request) + { + // PayPal doesn't support direct authorization. + + return $this; + } + + public function processPaymentView($data) { if (count($this->required_fields) > 0) { return redirect() @@ -186,37 +86,36 @@ public function checkRequirements() ->with('missing_required_fields', $this->required_fields); } - $response = $this->purchase($this->paymentDetails($data), $this->paymentItems($data)); + $this->initializeOmnipayGateway(); + + $this->payment_hash->data = array_merge((array) $this->payment_hash->data, ['amount' => $data['amount_with_fee']]); + $this->payment_hash->save(); + + $response = $this->omnipay_gateway + ->purchase($this->generatePaymentDetails($data)) + ->setItems($this->generatePaymentItems($data)) + ->send(); if ($response->isRedirect()) { - // redirect to offsite payment gateway - $response->redirect(); - } elseif ($response->isSuccessful()) { - // payment was successful: update database - /* for this driver this method wont be hit*/ - } else { - // payment failed: display message to customer - - SystemLogger::dispatch( - [ - 'server_response' => $response->getData(), - 'data' => $data, - ], - SystemLog::CATEGORY_GATEWAY_RESPONSE, - SystemLog::EVENT_GATEWAY_FAILURE, - SystemLog::TYPE_PAYPAL, - $this->client - ); - - throw new Exception('Error Processing Payment', 1); + return $response->redirect(); } - } - public function setPaymentHash(PaymentHash $payment_hash) - { - $this->payment_hash = $payment_hash; + PaymentFailureMailer::dispatch($this->client, $response->getData(), $this->client->company, $data['amount_with_fee']); - return $this; + $message = [ + 'server_response' => $response->getMessage(), + 'data' => $this->checkout->payment_hash->data, + ]; + + SystemLogger::dispatch( + $message, + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_FAILURE, + SystemLog::TYPE_PAYPAL, + $this->client + ); + + throw new PaymentFailed($response->getMessage(), $response->getCode()); } public function processPaymentResponse($request) @@ -226,210 +125,113 @@ public function checkRequirements() ->route('client.profile.edit', ['client_contact' => auth()->user()->hashed_id]) ->with('missing_required_fields', $this->required_fields); } - - $response = $this->completePurchase($request->all()); - $transaction_reference = $response->getTransactionReference() ?: $request->input('token'); + $this->initializeOmnipayGateway(); + + $response = $this->omnipay_gateway + ->completePurchase(['amount' => $this->payment_hash->data->amount]) + ->send(); if ($response->isCancelled()) { return redirect()->route('client.invoices.index')->with('warning', ctrans('texts.status_cancelled')); - } elseif ($response->isSuccessful()) { + } + + if ($response->isSuccessful()) { + $data = [ + 'payment_method' => $response->getData()['TOKEN'], + 'payment_type' => PaymentType::PAYPAL, + 'amount' => $this->payment_hash->data->amount, + 'transaction_reference' => $response->getTransactionReference(), + ]; + + $payment = $this->createPayment($data, \App\Models\Payment::STATUS_COMPLETED); + SystemLogger::dispatch( - [ - 'server_response' => $response->getData(), - 'data' => $request->all(), - ], + ['response' => $response, 'data' => $data], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_PAYPAL, $this->client ); - } elseif (! $response->isSuccessful()) { - PaymentFailureMailer::dispatch($this->client, $response->getMessage, $this->client->company, $response['PAYMENTINFO_0_AMT']); + + return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); + } + + if (!$response->isSuccessful()) { + PaymentFailureMailer::dispatch($this->client, $response->getMessage(), $this->client->company, $response['PAYMENTINFO_0_AMT']); + + $message = [ + 'server_response' => $response->getMessage(), + 'data' => $this->payment_hash->data, + ]; SystemLogger::dispatch( - [ - 'data' => $request->all(), - 'server_response' => $response->getData(), - ], + $message, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_PAYPAL, $this->client ); - throw new Exception($response->getMessage()); + throw new PaymentFailed($response->getMessage(), $response->getCode()); } - - $payment = $this->createPayment($response->getData()); - $payment_hash = PaymentHash::whereRaw('BINARY `hash`= ?', [$request->input('payment_hash')])->firstOrFail(); - - $payment_hash->payment_id = $payment->id; - $payment_hash->save(); - - $this->attachInvoices($payment, $payment_hash); - $payment->service()->updateInvoicePayment($payment_hash); - - event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars())); - - return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); } - protected function paymentDetails($input): array + public function generatePaymentDetails(array $data) { - $data = parent::paymentDetails($input); - - $data['amount'] = $input['amount_with_fee']; - $data['returnUrl'] = $this->buildReturnUrl($input); - $data['cancelUrl'] = $this->buildCancelUrl($input); - $data['description'] = $this->buildDescription($input); - $data['transactionId'] = $this->buildTransactionId($input); - - $data['ButtonSource'] = 'InvoiceNinja_SP'; - $data['solutionType'] = 'Sole'; // show 'Pay with credit card' option - $data['transactionId'] = $data['transactionId'].'-'.time(); - - return $data; - } - - private function buildReturnUrl($input): string - { - return route('client.payments.response', [ - 'company_gateway_id' => $this->company_gateway->id, - 'payment_hash' => $this->payment_hash->hash, - 'payment_method_id' => GatewayType::PAYPAL, - ]); - } - - private function buildCancelUrl($input): string - { - $url = $this->client->company->domain().'/client/invoices'; - - return $url; - } - - private function buildDescription($input): string - { - $invoice_numbers = ''; - - foreach ($input['invoices'] as $invoice) { - $invoice_numbers .= $invoice->number.' '; - } - - return ctrans('texts.invoice_number').": {$invoice_numbers}"; - } - - private function buildTransactionId($input): string - { - return implode(',', $input['hashed_ids']); - } - - private function paymentItems($input): array - { - $items = []; - $total = 0; - - foreach ($input['invoices'] as $invoice) { - foreach ($invoice->line_items as $invoiceItem) { - // Some gateways require quantity is an integer - if (floatval($invoiceItem->quantity) != intval($invoiceItem->quantity)) { - return null; - } - - $item = new Item([ - 'name' => $invoiceItem->product_key, - 'description' => substr($invoiceItem->notes, 0, 100), - 'price' => $invoiceItem->cost, - 'quantity' => $invoiceItem->quantity, - ]); - - $items[] = $item; - - $total += $invoiceItem->cost * $invoiceItem->quantity; - } - } - - if ($total != $input['amount_with_fee']) { - $item = new Item([ - 'name' => trans('texts.taxes_and_fees'), - 'description' => '', - 'price' => $input['amount_with_fee'] - $total, - 'quantity' => 1, - ]); - - $items[] = $item; - } - - return $items; - } - - public function createPayment($data, $status = Payment::STATUS_COMPLETED): Payment - { - $payment_meta = new stdClass; - $payment_meta->exp_month = 'xx'; - $payment_meta->exp_year = 'xx'; - $payment_meta->brand = 'PayPal'; - $payment_meta->last4 = 'xxxx'; - $payment_meta->type = GatewayType::PAYPAL; - - $payment = parent::createPayment($data, $status); - - $client_contact = $this->getContact(); - $client_contact_id = $client_contact ? $client_contact->id : null; - - $payment->amount = $data['PAYMENTINFO_0_AMT']; - $payment->type_id = PaymentType::PAYPAL; - $payment->transaction_reference = $data['PAYMENTINFO_0_TRANSACTIONID']; - $payment->client_contact_id = $client_contact_id; - $payment->meta = $payment_meta; - $payment->save(); - - return $payment; - } - - public function refund(Payment $payment, $amount) - { - $this->gateway(); - - $response = $this->gateway - ->refund(['transactionReference' => $payment->transaction_reference, 'amount' => $amount]) - ->send(); - - if ($response->isSuccessful()) { - SystemLogger::dispatch([ - 'server_response' => $response->getMessage(), 'data' => request()->all(), - ], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_PAYPAL, $this->client); - - return [ - 'transaction_reference' => $response->getData()['REFUNDTRANSACTIONID'], - 'transaction_response' => json_encode($response->getData()), - 'success' => true, - 'description' => $response->getData()['ACK'], - 'code' => $response->getCode(), - ]; - } - - SystemLogger::dispatch([ - 'server_response' => $response->getMessage(), 'data' => request()->all(), - ], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_PAYPAL, $this->client); - return [ - 'transaction_reference' => $response->getData()['CORRELATIONID'], - 'transaction_response' => json_encode($response->getData()), - 'success' => false, - 'description' => $response->getData()['L_LONGMESSAGE0'], - 'code' => $response->getData()['L_ERRORCODE0'], + 'currency' => $this->client->getCurrencyCode(), + 'transactionType' => 'Purchase', + 'clientIp' => request()->getClientIp(), + 'amount' => $data['amount_with_fee'], + 'returnUrl' => route('client.payments.response', [ + 'company_gateway_id' => $this->company_gateway->id, + 'payment_hash' => $this->payment_hash->hash, + 'payment_method_id' => GatewayType::PAYPAL, + ]), + 'cancelUrl' => $this->client->company->domain() . '/client/invoices', + 'description' => implode(',', collect($this->payment_hash->data->invoices) + ->map(function ($invoice) { + return sprintf('%s: %s', ctrans('texts.invoice_number'), $invoice->invoice_number); + })->toArray()), + 'transactionId' => $this->payment_hash->hash . '-' . time(), + 'ButtonSource' => 'InvoiceNinja_SP', + 'solutionType' => 'Sole', ]; } - /** - * Detach payment method from PayPal. - * - * @param ClientGatewayToken $token - * @return void - */ - public function detach(ClientGatewayToken $token) + public function generatePaymentItems(array $data) { - // PayPal doesn't support this feature. + $total = 0; + + $items = collect($this->payment_hash->data->invoices)->map(function ($i) use (&$total) { + $invoice = Invoice::findOrFail($this->decodePrimaryKey($i->invoice_id)); + + return collect($invoice->line_items)->map(function ($lineItem) use (&$total) { + if (floatval($lineItem->quantity) != intval($lineItem->quantity)) { + return null; + } + + $total += $lineItem->cost * $lineItem->quantity; + + return new Item([ + 'name' => $lineItem->product_key, + 'description' => substr($lineItem->notes, 0, 100), + 'price' => $lineItem->cost, + 'quantity' => $lineItem->quantity, + ]); + }); + }); + + if ($total != $data['amount_with_fee']) { + $items[0][] = new Item([ + 'name' => trans('texts.taxes_and_fees'), + 'description' => '', + 'price' => $data['amount_with_fee'] - $total, + 'quantity' => 1, + ]); + } + + return $items[0]->toArray(); } } diff --git a/app/Utils/PhantomJS/Phantom.php b/app/Utils/PhantomJS/Phantom.php index 6691142a042c..e6bbfca1fc07 100644 --- a/app/Utils/PhantomJS/Phantom.php +++ b/app/Utils/PhantomJS/Phantom.php @@ -22,10 +22,10 @@ use App\Utils\CurlUtils; use App\Utils\HtmlEngine; use App\Utils\Traits\MakesHash; use Illuminate\Support\Facades\App; +use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\Response; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; -use Illuminate\Support\Facades\Response; -use Illuminate\Support\Facades\Cache; class Phantom { @@ -90,7 +90,7 @@ class Phantom Cache::put($hash, $html, 300); $url = route('tmp_pdf', ['hash' => $hash]); -info($url); + info($url); $key = config('ninja.phantomjs_key'); $phantom_url = "https://phantomjscloud.com/api/browser/v2/{$key}/?request=%7Burl:%22{$url}%22,renderType:%22pdf%22%7D"; $pdf = CurlUtils::get($phantom_url); diff --git a/app/Utils/SystemHealth.php b/app/Utils/SystemHealth.php index 3abb9182d4b9..03a9904c8186 100644 --- a/app/Utils/SystemHealth.php +++ b/app/Utils/SystemHealth.php @@ -79,14 +79,15 @@ class SystemHealth 'npm_status' => self::checkNpm(), 'node_status' => self::checkNode(), 'cache_enabled' => self::checkConfigCache(), - 'phantom_enabled' => (bool) config('ninja.phantomjs_pdf_generation'), + 'phantom_enabled' => (bool) config('ninja.phantomjs_pdf_generation'), ]; } public static function checkConfigCache() { - if(env('APP_URL')) + if (env('APP_URL')) { return false; + } return true; } diff --git a/resources/views/email/template/master.blade.php b/resources/views/email/template/master.blade.php index 2c57def3affb..d2673becd23e 100644 --- a/resources/views/email/template/master.blade.php +++ b/resources/views/email/template/master.blade.php @@ -45,7 +45,9 @@ if(!isset($design)) $design = 'light'; {{ $greeting }} @endisset - {{ $slot }} +