mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 13:12:50 +01:00
Paypal Pro
This commit is contained in:
parent
29a8725f3f
commit
7c70bc5394
253
app/PaymentDrivers/PayPalProPaymentDriver.php
Normal file
253
app/PaymentDrivers/PayPalProPaymentDriver.php
Normal file
@ -0,0 +1,253 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\PaymentDrivers;
|
||||
|
||||
use App\Exceptions\PaymentFailed;
|
||||
use App\Jobs\Util\SystemLogger;
|
||||
use App\Models\GatewayType;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\PaymentType;
|
||||
use App\Models\SystemLog;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Omnipay\Common\Item;
|
||||
use Omnipay\Omnipay;
|
||||
|
||||
class PayPalProPaymentDriver extends BaseDriver
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
public $token_billing = false;
|
||||
|
||||
public $can_authorise_credit_card = false;
|
||||
|
||||
private $omnipay_gateway;
|
||||
|
||||
private float $fee = 0;
|
||||
|
||||
public const SYSTEM_LOG_TYPE = SystemLog::TYPE_PAYPAL;
|
||||
|
||||
public function gatewayTypes()
|
||||
{
|
||||
return [
|
||||
GatewayType::PAYPAL,
|
||||
];
|
||||
}
|
||||
|
||||
public function init()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Omnipay PayPal_Express gateway.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function initializeOmnipayGateway(): void
|
||||
{
|
||||
$this->omnipay_gateway = Omnipay::create(
|
||||
$this->company_gateway->gateway->provider
|
||||
);
|
||||
|
||||
$this->omnipay_gateway->initialize((array) $this->company_gateway->getConfig());
|
||||
}
|
||||
|
||||
public function setPaymentMethod($payment_method_id)
|
||||
{
|
||||
// PayPal doesn't have multiple ways of paying.
|
||||
// There's just one, off-site redirect.
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function authorizeView($payment_method)
|
||||
{
|
||||
// PayPal doesn't support direct authorization.
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function authorizeResponse($request)
|
||||
{
|
||||
// PayPal doesn't support direct authorization.
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function processPaymentView($data)
|
||||
{
|
||||
$this->initializeOmnipayGateway();
|
||||
|
||||
$data['gateway'] = $this;
|
||||
|
||||
$this->payment_hash->data = array_merge((array) $this->payment_hash->data, ['amount' => $data['total']['amount_with_fee']]);
|
||||
$this->payment_hash->save();
|
||||
|
||||
// $response = $this->omnipay_gateway
|
||||
// ->purchase($this->generatePaymentDetails($data))
|
||||
// ->setItems($this->generatePaymentItems($data))
|
||||
// ->send();
|
||||
|
||||
// if ($response->isRedirect()) {
|
||||
// return $response->redirect();
|
||||
// }
|
||||
|
||||
// $this->sendFailureMail($response->getMessage() ?: '');
|
||||
|
||||
// $message = [
|
||||
// 'server_response' => $response->getMessage(),
|
||||
// 'data' => $this->payment_hash->data,
|
||||
// ];
|
||||
|
||||
// SystemLogger::dispatch(
|
||||
// $message,
|
||||
// SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
// SystemLog::EVENT_GATEWAY_FAILURE,
|
||||
// SystemLog::TYPE_PAYPAL,
|
||||
// $this->client,
|
||||
// $this->client->company,
|
||||
// );
|
||||
|
||||
// throw new PaymentFailed($response->getMessage(), $response->getCode());
|
||||
|
||||
return render('gateways.paypal.pay', $data);
|
||||
|
||||
}
|
||||
|
||||
public function processPaymentResponse($request)
|
||||
{
|
||||
$this->initializeOmnipayGateway();
|
||||
|
||||
$response = $this->omnipay_gateway
|
||||
->completePurchase(['amount' => $this->payment_hash->data->amount, 'currency' => $this->client->getCurrencyCode()])
|
||||
->send();
|
||||
|
||||
if ($response->isCancelled() && $this->client->getSetting('enable_client_portal')) {
|
||||
return redirect()->route('client.invoices.index')->with('warning', ctrans('texts.status_cancelled'));
|
||||
} elseif ($response->isCancelled() && !$this->client->getSetting('enable_client_portal')) {
|
||||
redirect()->route('client.invoices.show', ['invoice' => $this->payment_hash->fee_invoice])->with('warning', ctrans('texts.status_cancelled'));
|
||||
}
|
||||
|
||||
if ($response->isSuccessful()) {
|
||||
$data = [
|
||||
'payment_method' => $response->getData()['TOKEN'],
|
||||
'payment_type' => PaymentType::PAYPAL,
|
||||
'amount' => $this->payment_hash->data->amount,
|
||||
'transaction_reference' => $response->getTransactionReference(),
|
||||
'gateway_type_id' => GatewayType::PAYPAL,
|
||||
];
|
||||
|
||||
$payment = $this->createPayment($data, \App\Models\Payment::STATUS_COMPLETED);
|
||||
|
||||
SystemLogger::dispatch(
|
||||
['response' => (array) $response->getData(), 'data' => $data],
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_SUCCESS,
|
||||
SystemLog::TYPE_PAYPAL,
|
||||
$this->client,
|
||||
$this->client->company,
|
||||
);
|
||||
|
||||
return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]);
|
||||
}
|
||||
|
||||
if (! $response->isSuccessful()) {
|
||||
$data = $response->getData();
|
||||
|
||||
$this->sendFailureMail($response->getMessage() ?: '');
|
||||
|
||||
$message = [
|
||||
'server_response' => $data['L_LONGMESSAGE0'],
|
||||
'data' => $this->payment_hash->data,
|
||||
];
|
||||
|
||||
SystemLogger::dispatch(
|
||||
$message,
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_FAILURE,
|
||||
SystemLog::TYPE_PAYPAL,
|
||||
$this->client,
|
||||
$this->client->company,
|
||||
);
|
||||
|
||||
throw new PaymentFailed($response->getMessage(), $response->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
public function generatePaymentDetails(array $data)
|
||||
{
|
||||
$_invoice = collect($this->payment_hash->data->invoices)->first();
|
||||
$invoice = Invoice::withTrashed()->find($this->decodePrimaryKey($_invoice->invoice_id));
|
||||
|
||||
// $this->fee = $this->feeCalc($invoice, $data['total']['amount_with_fee']);
|
||||
|
||||
return [
|
||||
'currency' => $this->client->getCurrencyCode(),
|
||||
'transactionType' => 'Purchase',
|
||||
'clientIp' => request()->getClientIp(),
|
||||
// 'amount' => round(($data['total']['amount_with_fee'] + $this->fee),2),
|
||||
'amount' => round($data['total']['amount_with_fee'], 2),
|
||||
'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/{$invoice->hashed_id}",
|
||||
'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',
|
||||
];
|
||||
}
|
||||
|
||||
public function generatePaymentItems(array $data)
|
||||
{
|
||||
$_invoice = collect($this->payment_hash->data->invoices)->first();
|
||||
$invoice = Invoice::withTrashed()->find($this->decodePrimaryKey($_invoice->invoice_id));
|
||||
|
||||
$items = [];
|
||||
|
||||
$items[] = new Item([
|
||||
'name' => ' ',
|
||||
'description' => ctrans('texts.invoice_number').'# '.$invoice->number,
|
||||
'price' => $data['total']['amount_with_fee'],
|
||||
'quantity' => 1,
|
||||
]);
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
private function feeCalc($invoice, $invoice_total)
|
||||
{
|
||||
$invoice->service()->removeUnpaidGatewayFees();
|
||||
$invoice = $invoice->fresh();
|
||||
|
||||
$balance = floatval($invoice->balance);
|
||||
|
||||
$_updated_invoice = $invoice->service()->addGatewayFee($this->company_gateway, GatewayType::PAYPAL, $invoice_total)->save();
|
||||
|
||||
if (floatval($_updated_invoice->balance) > $balance) {
|
||||
$fee = floatval($_updated_invoice->balance) - $balance;
|
||||
|
||||
$this->payment_hash->fee_total = $fee;
|
||||
$this->payment_hash->save();
|
||||
|
||||
return $fee;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' => ctrans('texts.payment_type_credit_card')])
|
||||
|
||||
@section('gateway_head')
|
||||
<link href="{{ asset('css/card-js.min.css') }}" rel="stylesheet" type="text/css">
|
||||
@endsection
|
||||
|
||||
@section('gateway_content')
|
||||
|
||||
<form style="display:none" target="hss_iframe" name="form_iframe"
|
||||
method="post"
|
||||
action="https://securepayments.paypal.com/webapps/HostedSoleSolutionApp/
|
||||
webflow/sparta/hostedSoleSolutionProcess">
|
||||
<input type="hidden" name="cmd" value="_hosted-payment">
|
||||
<input type="hidden" name="subtotal" value="{{ $total['amount_with_fee'] }}">
|
||||
<input type="hidden" name="business" value="{{ $gateway->company_gateway->getConfigField('username') }}">
|
||||
<input type="hidden" name="paymentaction" value="sale">
|
||||
<input type="hidden" name="template" value="templateD">
|
||||
<input type="hidden" name="return"
|
||||
value="https://yourwebsite.com/receipt_page.html">
|
||||
</form>
|
||||
|
||||
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_type')])
|
||||
{{ ctrans('texts.credit_card') }}
|
||||
@endcomponent
|
||||
|
||||
@include('portal.ninja2020.gateways.includes.payment_details')
|
||||
|
||||
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')])
|
||||
<iframe name="hss_iframe" width="570px" height="540px"></iframe>
|
||||
@endcomponent
|
||||
|
||||
@include('portal.ninja2020.gateways.includes.save_card')
|
||||
|
||||
@include('portal.ninja2020.gateways.includes.pay_now')
|
||||
@endsection
|
||||
|
||||
@section('gateway_footer')
|
||||
@endsection
|
||||
|
||||
@push('footer')
|
||||
|
||||
@endpush
|
Loading…
Reference in New Issue
Block a user