Working on Paypal REST integration

This commit is contained in:
David Bomba 2023-06-21 19:22:20 +10:00
parent 8e62c5ac51
commit f647139918
2 changed files with 157 additions and 105 deletions

View File

@ -37,6 +37,8 @@ class PayPalRestPaymentDriver extends BaseDriver
public const SYSTEM_LOG_TYPE = SystemLog::TYPE_PAYPAL;
private string $api_endpoint_url = '';
public function gatewayTypes()
{
return [
@ -45,16 +47,6 @@ class PayPalRestPaymentDriver extends BaseDriver
}
public function init()
{
return $this;
}
/**
* Initialize Omnipay PayPal_Express gateway.
*
* @return void
*/
private function initializeOmnipayGateway(): self
{
$this->omnipay_gateway = Omnipay::create(
$this->company_gateway->gateway->provider
@ -62,6 +54,8 @@ class PayPalRestPaymentDriver extends BaseDriver
$this->omnipay_gateway->initialize((array) $this->company_gateway->getConfig());
$this->api_endpoint_url = $this->company_gateway->getConfigField('testMode') ? 'https://api-m.sandbox.paypal.com' : 'https://api-m.paypal.com';
return $this;
}
@ -89,32 +83,121 @@ class PayPalRestPaymentDriver extends BaseDriver
public function processPaymentView($data)
{
$this->initializeOmnipayGateway();
$this->init();
$data['gateway'] = $this;
$this->payment_hash->data = array_merge((array) $this->payment_hash->data, ['amount' => $data['total']['amount_with_fee']]);
$this->payment_hash->save();
$access_token = $this->omnipay_gateway->getToken();
$headers = [
'Accept' => 'application/json',
'Content-type' => 'application/json',
'Accept-Language' => 'en_US',
];
$r = Http::withToken($access_token)
->withHeaders($headers)
->post("https://api-m.sandbox.paypal.com/v1/identity/generate-token",['body' => '']);
nlog($r->body());
dd($r);
$data['client_id'] = $this->company_gateway->getConfigField('clientId');
$data['token'] = $this->getClientToken();
$data['order_id'] = $this->createOrder($data);
return render('gateways.paypal.pay', $data);
}
public function processPaymentResponse($request)
{
$this->init();
nlog($request->all());
$response = json_decode($request['gateway_response'], true);
$order_id = $response['orderID'];
nlog($order_id);
$r = $this->gatewayRequest("/v2/checkout/orders/{$order_id}/capture", 'post', []);
dd($r->body());
}
private function getClientToken(): string
{
$r = $this->gatewayRequest('/v1/identity/generate-token', 'post', ['body' => '']);
if($r->successful())
return $r->json()['client_token'];
throw new PaymentFailed('Unable to gain client token from Paypal. Check your configuration', 401);
}
private function createOrder(array $data): string
{
$_invoice = collect($this->payment_hash->data->invoices)->first();
$invoice = Invoice::withTrashed()->find($this->decodePrimaryKey($_invoice->invoice_id));
$order = [
"intent" => "CAPTURE",
"purchase_units" => [
[
"description" =>ctrans('texts.invoice_number').'# '.$invoice->number,
"invoice_id" => $invoice->number,
'reference_id' => 'PUHF',
'description' => 'Sporting Goods',
'custom_id' => 'CUST-HighFashions',
'soft_descriptor' => 'HighFashions',
"amount" => [
"value" => (string)$data['amount_with_fee'],
"currency_code"=> $this->client->currency()->code,
"breakdown" => [
"item_total" => [
"currency_code" => $this->client->currency()->code,
"value" => (string)$data['amount_with_fee']
]
]
],
"items"=> [
[
"name" => ctrans('texts.invoice_number').'# '.$invoice->number,
"quantity" => "1",
"unit_amount" => [
"currency_code" => $this->client->currency()->code,
"value" => (string)$data['amount_with_fee']
],
],
],
]
]
];
$r = $this->gatewayRequest('/v2/checkout/orders', 'post', $order);
return $r->json()['id'];
}
public function gatewayRequest(string $uri, string $verb, array $data, ?array $headers = [])
{
$r = Http::withToken($this->omnipay_gateway->getToken())
->withHeaders($this->getHeaders($headers))
->{$verb}("{$this->api_endpoint_url}{$uri}", $data);
if($r->successful())
return $r;
throw new PaymentFailed("Gateway failure - {$r->body()}", 401);
}
private function getHeaders(array $headers = []): array
{
return array_merge([
'Accept' => 'application/json',
'Content-type' => 'application/json',
'Accept-Language' => 'en_US',
], $headers);
}
/*
public function processPaymentResponse($request)
{
$this->initializeOmnipayGateway();
@ -221,6 +304,8 @@ class PayPalRestPaymentDriver extends BaseDriver
return $items;
}
*/
private function feeCalc($invoice, $invoice_total)
{
$invoice->service()->removeUnpaidGatewayFees();
@ -241,4 +326,6 @@ class PayPalRestPaymentDriver extends BaseDriver
return 0;
}
}

View File

@ -1,8 +1,6 @@
@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">
<link
rel="stylesheet"
type="text/css"
@ -12,6 +10,15 @@
@endsection
@section('gateway_content')
<form action="{{ route('client.payments.response') }}" method="post" id="server_response">
@csrf
<input type="hidden" name="payment_hash" value="{{ $payment_hash }}">
<input type="hidden" name="company_gateway_id" value="{{ $gateway->company_gateway->id }}">
<input type="hidden" name="gateway_response" id="gateway_response">
<input type="hidden" name="amount_with_fee" id="amount_with_fee" value="{{ $total['amount_with_fee'] }}"/>
</form>
<div class="alert alert-failure mb-4" hidden id="errors"></div>
<div id="paypal-button-container" class="paypal-button-container"></div>
<div class="card_container">
@ -101,83 +108,16 @@
@endsection
@push('footer')
<script src="https://www.paypal.com/sdk/js?components=buttons,hosted-fields&client-id=AdRZZt44vJYAtXirmzMjnvUMoFIloN9kpuSgshQB7SJqLHbgtMP_rcmhy83FYY4a-c3R-_e4wZC8E3oG" data-client-token="{!! $token !!}">
<script src="https://www.paypal.com/sdk/js?components=buttons,hosted-fields&intent=capture&client-id={!! $client_id !!}" data-client-token="{!! $token !!}">
</script>
<script>
paypal
.Buttons({
// Sets up the transaction when a payment button is clicked
createOrder: function () {
return fetch("/api/orders", {
method: "post",
// use the "body" param to optionally pass additional order information
// like product skus and quantities
body: JSON.stringify({
cart: [
{
sku: "213434",
quantity: "1",
},
],
}),
})
.then((response) => response.json())
.then((order) => order.id);
},
// Finalize the transaction after payer approval
onApprove: function (data) {
return fetch(`/api/orders/${data.orderID}/capture`, {
method: "post",
})
.then((response) => response.json())
.then((orderData) => {
// Successful capture! For dev/demo purposes:
console.log(
"Capture result",
orderData,
JSON.stringify(orderData, null, 2)
);
const transaction = orderData.purchase_units[0].payments.captures[0];
alert(`Transaction ${transaction.status}: ${transaction.id}
See console for all available details
`);
// When ready to go live, remove the alert and show a success message within this page. For example:
// var element = document.getElementById('paypal-button-container');
// element.innerHTML = '<h3>Thank you for your payment!</h3>';
// Or go to another URL: actions.redirect('thank_you.html');
});
},
})
.render("#paypal-button-container");
// If this returns false or the card fields aren't visible, see Step #1.
if (paypal.HostedFields.isEligible()) {
let orderId;
// Renders card fields
paypal.HostedFields.render({
// Call your server to set up the transaction
createOrder: () => {
return fetch("/api/orders", {
method: "post",
// use the "body" param to optionally pass additional order information
// like product skus and quantities
body: JSON.stringify({
cart: [
{
sku: "cxcxcx",
quantity: "333",
},
],
}),
})
.then((res) => res.json())
.then((orderData) => {
orderId = orderData.id; // needed later to complete capture
return orderData.id;
});
createOrder: function(data, actions) {
return "{!! $order_id !!}"
},
styles: {
".valid": {
@ -261,9 +201,34 @@ if (paypal.HostedFields.isEligible()) {
});
});
});
} else {
// Hides card fields if the merchant isn't eligible
document.querySelector("#card-form").style = "display: none";
}
else {
document.querySelector("#card-form").style = "display: none";
paypal.Buttons({
env: 'sandbox', // sandbox | production
client: {
sandbox: "{{ $gateway->company_gateway->getConfigField('clientId') }}",
},
createOrder: function(data, actions) {
return "{!! $order_id !!}"
},
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
console.log(details);
});
// document.getElementById("gateway_response").value =JSON.stringify( data );
// document.getElementById("server_response").submit();
}
}).render('#paypal-button-container');
}
</script>
@endpush