Working on ApplePay

This commit is contained in:
David Bomba 2021-08-16 08:54:11 +10:00
parent 6669b81c4d
commit cde5f527e1
4 changed files with 207 additions and 3 deletions

View 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);
}
}

View File

@ -108,7 +108,7 @@ class CreditCard
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);
@ -148,7 +148,7 @@ class CreditCard
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);

View File

@ -25,6 +25,7 @@ use App\Models\PaymentHash;
use App\Models\SystemLog;
use App\PaymentDrivers\Stripe\ACH;
use App\PaymentDrivers\Stripe\Alipay;
use App\PaymentDrivers\Stripe\ApplePay;
use App\PaymentDrivers\Stripe\Charge;
use App\PaymentDrivers\Stripe\Connect\Verify;
use App\PaymentDrivers\Stripe\CreditCard;
@ -72,7 +73,7 @@ class StripePaymentDriver extends BaseDriver
GatewayType::BANK_TRANSFER => ACH::class,
GatewayType::ALIPAY => Alipay::class,
GatewayType::SOFORT => SOFORT::class,
GatewayType::APPLE_PAY => 1, // TODO
GatewayType::APPLE_PAY => ApplePay::class,
GatewayType::SEPA => 1, // TODO
];

View File

@ -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