1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-10 21:22:58 +01:00
invoiceninja/app/PaymentDrivers/Stripe/BrowserPay.php

235 lines
7.7 KiB
PHP
Raw Normal View History

2021-10-31 14:45:01 +01:00
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
2022-04-27 05:20:41 +02:00
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
2021-10-31 14:45:01 +01:00
*
* @license https://www.elastic.co/licensing/elastic-license
2021-10-31 14:45:01 +01:00
*/
namespace App\PaymentDrivers\Stripe;
2021-11-01 14:39:18 +01:00
use App\Exceptions\PaymentFailed;
2021-10-31 14:45:01 +01:00
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
2021-11-01 14:39:18 +01:00
use App\Jobs\Util\SystemLogger;
use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\Common\MethodInterface;
2021-10-31 15:12:02 +01:00
use App\PaymentDrivers\StripePaymentDriver;
use App\Utils\Ninja;
2021-10-31 14:52:15 +01:00
use Illuminate\Http\RedirectResponse;
2021-11-01 14:39:18 +01:00
use Illuminate\Http\Request;
2021-10-31 16:49:58 +01:00
use Illuminate\View\View;
2021-10-31 15:12:02 +01:00
use Stripe\ApplePayDomain;
use Stripe\Exception\ApiErrorException;
2021-11-01 14:39:18 +01:00
use Stripe\PaymentIntent;
2021-10-31 14:45:01 +01:00
class BrowserPay implements MethodInterface
{
2021-10-31 15:12:02 +01:00
protected StripePaymentDriver $stripe;
public function __construct(StripePaymentDriver $stripe)
{
$this->stripe = $stripe;
$this->stripe->init();
$this->ensureApplePayDomainIsValidated();
}
2021-10-31 14:52:15 +01:00
/**
* Authorization page for browser pay.
2021-11-01 14:39:18 +01:00
*
* @param array $data
* @return RedirectResponse
2021-10-31 14:52:15 +01:00
*/
public function authorizeView(array $data): RedirectResponse
{
return redirect()->route('client.payment_methods.index');
}
2021-10-31 14:45:01 +01:00
2021-10-31 14:52:15 +01:00
/**
* Handle the authorization for browser pay.
2021-11-01 14:39:18 +01:00
*
* @param Request $request
* @return RedirectResponse
2021-10-31 14:52:15 +01:00
*/
public function authorizeResponse(Request $request): RedirectResponse
{
return redirect()->route('client.payment_methods.index');
}
2021-10-31 14:45:01 +01:00
2021-10-31 16:49:58 +01:00
public function paymentView(array $data): View
{
$payment_intent_data = [
'amount' => $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency()),
'currency' => $this->stripe->client->getCurrencyCode(),
'customer' => $this->stripe->findOrCreateCustomer(),
'description' => $this->stripe->decodeUnicodeString(ctrans('texts.invoices').': '.collect($data['invoices'])->pluck('invoice_number')),
'metadata' => [
'payment_hash' => $this->stripe->payment_hash->hash,
'gateway_type_id' => GatewayType::APPLE_PAY,
],
2021-10-31 16:49:58 +01:00
];
$data['gateway'] = $this->stripe;
$data['pi_client_secret'] = $this->stripe->createPaymentIntent($payment_intent_data)->client_secret;
$data['payment_request_data'] = [
'country' => $this->stripe->client->country->iso_3166_2,
'currency' => strtolower(
$this->stripe->client->getCurrencyCode()
),
'total' => [
'label' => $payment_intent_data['description'],
'amount' => $payment_intent_data['amount'],
],
'requestPayerName' => true,
'requestPayerEmail' => true,
2021-10-31 16:49:58 +01:00
];
2021-11-01 14:39:18 +01:00
return render('gateways.stripe.browser_pay.pay', $data);
}
/**
* Handle payment response for browser pay.
*
* @param PaymentResponseRequest $request
* @return RedirectResponse|App\PaymentDrivers\Stripe\never
*/
public function paymentResponse(PaymentResponseRequest $request)
{
$gateway_response = json_decode($request->gateway_response);
2021-11-01 14:39:18 +01:00
$this->stripe->payment_hash
->withData('gateway_response', $gateway_response)
->withData('payment_intent', PaymentIntent::retrieve($gateway_response->id, $this->stripe->stripe_connect_auth));
if ($gateway_response->status === 'succeeded') {
return $this->processSuccessfulPayment();
}
return $this->processUnsuccessfulPayment();
2021-10-31 16:49:58 +01:00
}
2021-10-31 14:45:01 +01:00
2021-11-01 14:39:18 +01:00
/**
* Handle successful payment for browser pay.
*
* @return RedirectResponse
*/
protected function processSuccessfulPayment()
{
$gateway_response = $this->stripe->payment_hash->data->gateway_response;
$payment_intent = $this->stripe->payment_hash->data->payment_intent;
$this->stripe->logSuccessfulGatewayResponse(['response' => $gateway_response, 'data' => $this->stripe->payment_hash], SystemLog::TYPE_STRIPE);
$payment_method = $this->stripe->getStripePaymentMethod($gateway_response->payment_method);
$data = [
'payment_method' => $gateway_response->payment_method,
'payment_type' => PaymentType::parseCardType(strtolower($payment_method->card->brand)),
'amount' => $this->stripe->convertFromStripeAmount($gateway_response->amount, $this->stripe->client->currency()->precision, $this->stripe->client->currency()),
2022-11-29 10:09:54 +01:00
'transaction_reference' => isset($payment_intent->latest_charge) ? $payment_intent->latest_charge : $payment_intent->charges->data[0]->id,
2021-11-01 14:39:18 +01:00
'gateway_type_id' => GatewayType::APPLE_PAY,
];
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['amount' => $data['amount']]);
$this->stripe->payment_hash->save();
$payment = $this->stripe->createPayment($data, Payment::STATUS_COMPLETED);
SystemLogger::dispatch(
['response' => $gateway_response, 'data' => $data],
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_SUCCESS,
SystemLog::TYPE_STRIPE,
$this->stripe->client,
$this->stripe->client->company,
);
return redirect()->route('client.payments.show', ['payment' => $this->stripe->encodePrimaryKey($payment->id)]);
}
/**
* Handle unsuccessful payment for browser pay.
*
* @return never
*/
protected function processUnsuccessfulPayment()
{
$server_response = $this->stripe->payment_hash->data->gateway_response;
$this->stripe->sendFailureMail($server_response->cancellation_reason);
$message = [
'server_response' => $server_response,
'data' => $this->stripe->payment_hash->data,
];
SystemLogger::dispatch(
$message,
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_FAILURE,
SystemLog::TYPE_STRIPE,
$this->stripe->client,
$this->stripe->client->company,
);
throw new PaymentFailed('Failed to process the payment.', 500);
}
2021-10-31 15:12:02 +01:00
/**
* Ensure Apple Pay domain is verified.
2021-11-01 14:39:18 +01:00
*
* @return void
* @throws ApiErrorException
2021-10-31 15:12:02 +01:00
*/
protected function ensureApplePayDomainIsValidated()
{
$config = $this->stripe->company_gateway->getConfig();
if (property_exists($config, 'apple_pay_domain_id')) {
return;
}
2022-01-10 02:47:16 +01:00
$domain = $this->getAppleDomain();
if (! $domain) {
2022-01-10 02:47:16 +01:00
throw new PaymentFailed('Unable to register Domain with Apple Pay', 500);
}
2021-10-31 15:12:02 +01:00
$response = ApplePayDomain::create([
'domain_name' => $domain,
], $this->stripe->stripe_connect_auth);
2021-10-31 15:12:02 +01:00
$config->apple_pay_domain_id = $response->id;
$this->stripe->company_gateway->setConfig($config);
2021-10-31 15:12:02 +01:00
$this->stripe->company_gateway->save();
}
2022-01-10 02:47:16 +01:00
private function getAppleDomain()
{
$domain = '';
if (Ninja::isHosted()) {
if ($this->stripe->company_gateway->company->portal_mode == 'domain') {
2022-01-17 11:22:10 +01:00
$domain = $this->stripe->company_gateway->company->portal_domain;
} else {
$domain = $this->stripe->company_gateway->company->subdomain.'.'.config('ninja.app_domain');
2022-01-10 02:47:16 +01:00
}
} else {
2022-01-10 02:47:16 +01:00
$domain = config('ninja.app_url');
}
return str_replace('https://', '', $domain);
2022-01-10 02:47:16 +01:00
}
2021-11-01 14:39:18 +01:00
}