1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-20 08:21:34 +02:00
invoiceninja/app/PaymentDrivers/PayPalExpressPaymentDriver.php

238 lines
7.5 KiB
PHP
Raw Normal View History

2019-09-26 07:14:07 +02:00
<?php
2019-09-26 07:14:07 +02:00
/**
* Invoice Ninja (https://invoiceninja.com).
2019-09-26 07:14:07 +02:00
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
2019-09-26 07:14:07 +02:00
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\PaymentDrivers;
2020-11-26 16:36:43 +01:00
use App\Exceptions\PaymentFailed;
use App\Jobs\Mail\PaymentFailureMailer;
use App\Jobs\Util\SystemLogger;
2019-09-26 07:14:07 +02:00
use App\Models\GatewayType;
2020-11-26 16:36:43 +01:00
use App\Models\Invoice;
2019-10-01 03:56:48 +02:00
use App\Models\PaymentType;
use App\Models\SystemLog;
2019-09-26 07:14:07 +02:00
use App\Utils\Traits\MakesHash;
2019-09-30 01:26:37 +02:00
use Omnipay\Common\Item;
2020-11-26 16:36:43 +01:00
use Omnipay\Omnipay;
class PayPalExpressPaymentDriver extends BaseDriver
2019-09-26 07:14:07 +02:00
{
use MakesHash;
2019-09-26 07:14:07 +02:00
2020-11-26 16:36:43 +01:00
public $token_billing = false;
2019-09-26 07:14:07 +02:00
2020-11-26 16:36:43 +01:00
public $can_authorise_credit_card = false;
2019-09-26 07:14:07 +02:00
2020-11-26 16:36:43 +01:00
private $omnipay_gateway;
2019-09-26 07:14:07 +02:00
2020-11-26 16:36:43 +01:00
const SYSTEM_LOG_TYPE = SystemLog::TYPE_PAYPAL;
2019-09-26 07:14:07 +02:00
public function gatewayTypes()
{
return [
GatewayType::PAYPAL,
];
}
2020-11-26 16:36:43 +01:00
/**
* Initialize Omnipay PayPal_Express gateway.
2020-11-27 11:12:05 +01:00
*
* @return void
2020-11-26 16:36:43 +01:00
*/
private function initializeOmnipayGateway(): void
{
2020-11-26 16:36:43 +01:00
$this->omnipay_gateway = Omnipay::create(
$this->company_gateway->gateway->provider
);
2020-11-26 16:36:43 +01:00
$this->omnipay_gateway->initialize((array) $this->company_gateway->getConfig());
}
2020-11-26 16:36:43 +01:00
public function setPaymentMethod($payment_method_id)
{
2020-11-27 11:12:05 +01:00
// PayPal doesn't have multiple ways of paying.
2020-11-26 16:36:43 +01:00
// There's just one, off-site redirect.
2020-11-26 16:36:43 +01:00
return $this;
}
2020-11-26 16:36:43 +01:00
public function authorizeView($payment_method)
{
// PayPal doesn't support direct authorization.
return $this;
}
2020-11-26 16:36:43 +01:00
public function authorizeResponse($request)
{
2020-11-26 16:36:43 +01:00
// PayPal doesn't support direct authorization.
2020-11-26 16:36:43 +01:00
return $this;
}
2020-11-26 16:36:43 +01:00
public function processPaymentView($data)
2019-09-26 07:14:07 +02:00
{
2020-11-27 11:12:05 +01:00
if (count($this->required_fields) > 0) {
return redirect()
->route('client.profile.edit', ['client_contact' => auth()->user()->hashed_id])
->with('missing_required_fields', $this->required_fields);
}
2020-11-26 16:36:43 +01:00
$this->initializeOmnipayGateway();
$this->payment_hash->data = array_merge((array) $this->payment_hash->data, ['amount' => $data['amount_with_fee']]);
$this->payment_hash->save();
2020-11-26 16:36:43 +01:00
$response = $this->omnipay_gateway
->purchase($this->generatePaymentDetails($data))
->setItems($this->generatePaymentItems($data))
->send();
2019-10-02 00:44:13 +02:00
if ($response->isRedirect()) {
2020-11-26 16:36:43 +01:00
return $response->redirect();
}
2019-10-02 00:44:13 +02:00
2020-11-26 16:36:43 +01:00
PaymentFailureMailer::dispatch($this->client, $response->getData(), $this->client->company, $data['amount_with_fee']);
2019-10-02 00:44:13 +02:00
2020-11-26 16:36:43 +01:00
$message = [
'server_response' => $response->getMessage(),
'data' => $this->checkout->payment_hash->data,
];
2019-09-26 07:14:07 +02:00
2020-11-26 16:36:43 +01:00
SystemLogger::dispatch(
$message,
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_FAILURE,
SystemLog::TYPE_PAYPAL,
$this->client
);
2020-11-26 16:36:43 +01:00
throw new PaymentFailed($response->getMessage(), $response->getCode());
}
2019-09-26 07:14:07 +02:00
public function processPaymentResponse($request)
{
2020-11-27 11:12:05 +01:00
if (count($this->required_fields) > 0) {
return redirect()
->route('client.profile.edit', ['client_contact' => auth()->user()->hashed_id])
->with('missing_required_fields', $this->required_fields);
}
2020-11-26 16:36:43 +01:00
$this->initializeOmnipayGateway();
2019-10-01 03:56:48 +02:00
2020-11-26 16:36:43 +01:00
$response = $this->omnipay_gateway
->completePurchase(['amount' => $this->payment_hash->data->amount])
->send();
2019-09-30 03:15:57 +02:00
if ($response->isCancelled()) {
2020-07-06 13:22:36 +02:00
return redirect()->route('client.invoices.index')->with('warning', ctrans('texts.status_cancelled'));
2020-11-26 16:36:43 +01:00
}
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(
2020-11-26 16:36:43 +01:00
['response' => $response, 'data' => $data],
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_SUCCESS,
SystemLog::TYPE_PAYPAL,
$this->client
);
2020-11-26 16:36:43 +01:00
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(
2020-11-26 16:36:43 +01:00
$message,
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_FAILURE,
SystemLog::TYPE_PAYPAL,
$this->client
);
2019-10-02 00:44:13 +02:00
2020-11-26 16:36:43 +01:00
throw new PaymentFailed($response->getMessage(), $response->getCode());
2019-09-30 01:26:37 +02:00
}
2019-09-29 23:49:43 +02:00
}
2019-09-30 01:26:37 +02:00
2020-11-26 16:36:43 +01:00
public function generatePaymentDetails(array $data)
2019-09-30 01:26:37 +02:00
{
2020-11-26 16:36:43 +01:00
return [
'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',
];
2019-09-30 01:26:37 +02:00
}
2020-11-26 16:36:43 +01:00
public function generatePaymentItems(array $data)
2019-09-30 01:26:37 +02:00
{
$total = 0;
2020-11-26 16:36:43 +01:00
$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)) {
2019-09-30 01:26:37 +02:00
return null;
}
2020-11-26 16:36:43 +01:00
$total += $lineItem->cost * $lineItem->quantity;
2019-09-30 01:26:37 +02:00
2020-11-26 16:36:43 +01:00
return new Item([
'name' => $lineItem->product_key,
'description' => substr($lineItem->notes, 0, 100),
'price' => $lineItem->cost,
'quantity' => $lineItem->quantity,
]);
});
});
2019-09-30 01:26:37 +02:00
2020-11-26 16:36:43 +01:00
if ($total != $data['amount_with_fee']) {
$items[0][] = new Item([
2019-09-30 01:26:37 +02:00
'name' => trans('texts.taxes_and_fees'),
'description' => '',
2020-11-26 16:36:43 +01:00
'price' => $data['amount_with_fee'] - $total,
2019-09-30 01:26:37 +02:00
'quantity' => 1,
]);
}
2020-11-26 16:36:43 +01:00
return $items[0]->toArray();
}
}