mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Working on ApplePay
This commit is contained in:
parent
6669b81c4d
commit
cde5f527e1
91
app/PaymentDrivers/Stripe/ApplePay.php
Normal file
91
app/PaymentDrivers/Stripe/ApplePay.php
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\PaymentDrivers\Stripe;
|
||||||
|
|
||||||
|
use App\Exceptions\PaymentFailed;
|
||||||
|
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
|
||||||
|
use App\Jobs\Mail\PaymentFailureMailer;
|
||||||
|
use App\Jobs\Util\SystemLogger;
|
||||||
|
use App\Models\GatewayType;
|
||||||
|
use App\Models\Payment;
|
||||||
|
use App\Models\PaymentType;
|
||||||
|
use App\Models\SystemLog;
|
||||||
|
use App\PaymentDrivers\StripePaymentDriver;
|
||||||
|
use App\PaymentDrivers\Stripe\CreditCard;
|
||||||
|
|
||||||
|
class ApplePay
|
||||||
|
{
|
||||||
|
/** @var StripePaymentDriver */
|
||||||
|
public $stripe_driver;
|
||||||
|
|
||||||
|
public function __construct(StripePaymentDriver $stripe_driver)
|
||||||
|
{
|
||||||
|
$this->stripe_driver = $stripe_driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function paymentView(array $data)
|
||||||
|
{
|
||||||
|
$data['gateway'] = $this->stripe_driver;
|
||||||
|
$data['payment_hash'] = $this->stripe_driver->payment_hash->hash;
|
||||||
|
$data['payment_method_id'] = GatewayType::APPLE_PAY;
|
||||||
|
$data['country'] = $this->stripe_driver->client->country;
|
||||||
|
$data['currency'] = $this->stripe_driver->client->currency()->code;
|
||||||
|
$data['stripe_amount'] = $this->stripe_driver->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe_driver->client->currency()->precision, $this->stripe_driver->client->currency());
|
||||||
|
$data['invoices'] = $this->stripe_driver->payment_hash->invoices();
|
||||||
|
|
||||||
|
$data['intent'] = \Stripe\PaymentIntent::create([
|
||||||
|
'amount' => $data['stripe_amount'],
|
||||||
|
'currency' => $this->stripe_driver->client->getCurrencyCode();,
|
||||||
|
], $this->stripe_driver->stripe_connect_auth);
|
||||||
|
|
||||||
|
$this->stripe_driver->payment_hash->data = array_merge((array) $this->stripe_driver->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]);
|
||||||
|
$this->stripe_driver->payment_hash->save();
|
||||||
|
|
||||||
|
return render('gateways.stripe.applepay.pay', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function paymentResponse(PaymentResponseRequest $request)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->stripe_driver->init();
|
||||||
|
|
||||||
|
$state = [
|
||||||
|
'server_response' => json_decode($request->gateway_response),
|
||||||
|
'payment_hash' => $request->payment_hash,
|
||||||
|
];
|
||||||
|
|
||||||
|
$state['payment_intent'] = \Stripe\PaymentIntent::retrieve($state['server_response']->id, $this->stripe_driver->stripe_connect_auth);
|
||||||
|
|
||||||
|
$state['customer'] = $state['payment_intent']->customer;
|
||||||
|
|
||||||
|
$this->stripe_driver->payment_hash->data = array_merge((array) $this->stripe_driver->payment_hash->data, $state);
|
||||||
|
$this->stripe_driver->payment_hash->save();
|
||||||
|
|
||||||
|
$server_response = $this->stripe_driver->payment_hash->data->server_response;
|
||||||
|
|
||||||
|
$response_handler = new CreditCard($this->stripe_driver);
|
||||||
|
|
||||||
|
if ($server_response->status == 'succeeded') {
|
||||||
|
|
||||||
|
$this->stripe_driver->logSuccessfulGatewayResponse(['response' => json_decode($request->gateway_response), 'data' => $this->stripe_driver->payment_hash], SystemLog::TYPE_STRIPE);
|
||||||
|
|
||||||
|
return $response_handler->processSuccessfulPayment();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response_handler->processUnsuccessfulPayment($server_response);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -108,7 +108,7 @@ class CreditCard
|
|||||||
return $this->processUnsuccessfulPayment($server_response);
|
return $this->processUnsuccessfulPayment($server_response);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function processSuccessfulPayment()
|
public function processSuccessfulPayment()
|
||||||
{
|
{
|
||||||
$stripe_method = $this->stripe->getStripePaymentMethod($this->stripe->payment_hash->data->server_response->payment_method);
|
$stripe_method = $this->stripe->getStripePaymentMethod($this->stripe->payment_hash->data->server_response->payment_method);
|
||||||
|
|
||||||
@ -148,7 +148,7 @@ class CreditCard
|
|||||||
return redirect()->route('client.payments.show', ['payment' => $this->stripe->encodePrimaryKey($payment->id)]);
|
return redirect()->route('client.payments.show', ['payment' => $this->stripe->encodePrimaryKey($payment->id)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function processUnsuccessfulPayment($server_response)
|
public function processUnsuccessfulPayment($server_response)
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ use App\Models\PaymentHash;
|
|||||||
use App\Models\SystemLog;
|
use App\Models\SystemLog;
|
||||||
use App\PaymentDrivers\Stripe\ACH;
|
use App\PaymentDrivers\Stripe\ACH;
|
||||||
use App\PaymentDrivers\Stripe\Alipay;
|
use App\PaymentDrivers\Stripe\Alipay;
|
||||||
|
use App\PaymentDrivers\Stripe\ApplePay;
|
||||||
use App\PaymentDrivers\Stripe\Charge;
|
use App\PaymentDrivers\Stripe\Charge;
|
||||||
use App\PaymentDrivers\Stripe\Connect\Verify;
|
use App\PaymentDrivers\Stripe\Connect\Verify;
|
||||||
use App\PaymentDrivers\Stripe\CreditCard;
|
use App\PaymentDrivers\Stripe\CreditCard;
|
||||||
@ -72,7 +73,7 @@ class StripePaymentDriver extends BaseDriver
|
|||||||
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, // TODO
|
GatewayType::APPLE_PAY => ApplePay::class,
|
||||||
GatewayType::SEPA => 1, // TODO
|
GatewayType::SEPA => 1, // TODO
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -0,0 +1,112 @@
|
|||||||
|
@extends('portal.ninja2020.layout.payments', ['gateway_title' => 'Alipay', 'card_title' => 'Alipay'])
|
||||||
|
|
||||||
|
@section('gateway_head')
|
||||||
|
|
||||||
|
@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="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>
|
||||||
|
|
||||||
|
@include('portal.ninja2020.gateways.includes.payment_details')
|
||||||
|
|
||||||
|
<div id="payment-request-button">
|
||||||
|
<!-- A Stripe Element will be inserted here. -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@push('footer')
|
||||||
|
<script src="https://js.stripe.com/v3/"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
@if($gateway->company_gateway->getConfigField('account_id'))
|
||||||
|
var stripe = Stripe('{{ config('ninja.ninja_stripe_publishable_key') }}', {
|
||||||
|
apiVersion: "2018-05-21",
|
||||||
|
stripeAccount: '{{ $gateway->company_gateway->getConfigField('account_id') }}',
|
||||||
|
});
|
||||||
|
@else
|
||||||
|
var stripe = Stripe('{{ $gateway->getPublishableKey() }}', {
|
||||||
|
apiVersion: "2018-05-21",
|
||||||
|
});
|
||||||
|
@endif
|
||||||
|
|
||||||
|
var paymentRequest = stripe.paymentRequest({
|
||||||
|
country: '{{ $country->iso_3166_2 }}',
|
||||||
|
currency: '{{ $currency }}',
|
||||||
|
total: {
|
||||||
|
label: '{{ ctrans('texts.payment_amount') }}',
|
||||||
|
amount: {{ $stripe_amount }},
|
||||||
|
},
|
||||||
|
requestPayerName: true,
|
||||||
|
requestPayerEmail: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
var elements = stripe.elements();
|
||||||
|
var prButton = elements.create('paymentRequestButton', {
|
||||||
|
paymentRequest: paymentRequest,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check the availability of the Payment Request API first.
|
||||||
|
paymentRequest.canMakePayment().then(function(result) {
|
||||||
|
if (result) {
|
||||||
|
prButton.mount('#payment-request-button');
|
||||||
|
} else {
|
||||||
|
document.getElementById('payment-request-button').style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
paymentRequest.on('paymentmethod', function(ev) {
|
||||||
|
// Confirm the PaymentIntent without handling potential next actions (yet).
|
||||||
|
stripe.confirmCardPayment(
|
||||||
|
'{{ $intent->client_secret }}',
|
||||||
|
{payment_method: ev.paymentMethod.id},
|
||||||
|
{handleActions: false}
|
||||||
|
).then(function(confirmResult) {
|
||||||
|
if (confirmResult.error) {
|
||||||
|
// Report to the browser that the payment failed, prompting it to
|
||||||
|
// re-show the payment interface, or show an error message and close
|
||||||
|
// the payment interface.
|
||||||
|
ev.complete('fail');
|
||||||
|
} else {
|
||||||
|
// Report to the browser that the confirmation was successful, prompting
|
||||||
|
// it to close the browser payment method collection interface.
|
||||||
|
ev.complete('success');
|
||||||
|
// Check if the PaymentIntent requires any actions and if so let Stripe.js
|
||||||
|
// handle the flow. If using an API version older than "2019-02-11"
|
||||||
|
// instead check for: `paymentIntent.status === "requires_source_action"`.
|
||||||
|
if (confirmResult.paymentIntent.status === "requires_action") {
|
||||||
|
// Let Stripe.js handle the rest of the payment flow.
|
||||||
|
stripe.confirmCardPayment(clientSecret).then(function(result) {
|
||||||
|
if (result.error) {
|
||||||
|
// The payment failed -- ask your customer for a new payment method.
|
||||||
|
} else {
|
||||||
|
// The payment has succeeded.
|
||||||
|
handleSuccess(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// The payment has succeeded.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
handleSuccess(result) {
|
||||||
|
document.querySelector(
|
||||||
|
'input[name="gateway_response"]'
|
||||||
|
).value = JSON.stringify(result.paymentIntent);
|
||||||
|
|
||||||
|
document.getElementById('server-response').submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
@endpush
|
Loading…
x
Reference in New Issue
Block a user