2023-10-16 03:05:19 +02:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Invoice Ninja (https://invoiceninja.com).
|
|
|
|
*
|
|
|
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
|
|
|
*
|
2024-04-12 06:15:41 +02:00
|
|
|
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
2023-10-16 03:05:19 +02:00
|
|
|
*
|
|
|
|
* @license https://www.elastic.co/licensing/elastic-license
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace App\PaymentDrivers;
|
|
|
|
|
2023-12-13 07:10:29 +01:00
|
|
|
use Str;
|
|
|
|
use Carbon\Carbon;
|
2023-10-16 03:05:19 +02:00
|
|
|
use App\Models\Invoice;
|
|
|
|
use App\Models\SystemLog;
|
2023-12-13 07:10:29 +01:00
|
|
|
use App\Models\GatewayType;
|
2024-06-13 08:52:23 +02:00
|
|
|
use App\Models\PaymentHash;
|
2023-12-13 07:10:29 +01:00
|
|
|
use App\Models\PaymentType;
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
use App\Jobs\Util\SystemLogger;
|
2023-10-16 03:05:19 +02:00
|
|
|
use App\Utils\Traits\MakesHash;
|
2023-12-13 07:10:29 +01:00
|
|
|
use App\Exceptions\PaymentFailed;
|
2024-05-20 03:59:44 +02:00
|
|
|
use App\Models\ClientGatewayToken;
|
2023-10-16 03:05:19 +02:00
|
|
|
use Illuminate\Support\Facades\Http;
|
2023-12-13 07:10:29 +01:00
|
|
|
use App\PaymentDrivers\PayPal\PayPalWebhook;
|
2024-05-20 03:59:44 +02:00
|
|
|
use App\PaymentDrivers\PayPal\PayPalBasePaymentDriver;
|
2023-10-16 03:05:19 +02:00
|
|
|
|
2024-05-20 03:59:44 +02:00
|
|
|
class PayPalPPCPPaymentDriver extends PayPalBasePaymentDriver
|
2023-10-16 03:05:19 +02:00
|
|
|
{
|
|
|
|
use MakesHash;
|
2024-05-20 03:59:44 +02:00
|
|
|
|
|
|
|
///v1/customer/partners/merchant-accounts/{merchant_id}/capabilities - test if advanced cards is available.
|
|
|
|
// {
|
|
|
|
// "capabilities": [
|
|
|
|
// {
|
|
|
|
// "name": "ADVANCED_CARD_PAYMENTS",
|
|
|
|
// "status": "ENABLED"
|
|
|
|
// },
|
|
|
|
// {
|
|
|
|
// "name": "VAULTING",
|
|
|
|
// "status": "ENABLED"
|
|
|
|
// }
|
|
|
|
// ]
|
|
|
|
// }
|
2023-10-16 03:05:19 +02:00
|
|
|
|
|
|
|
public const SYSTEM_LOG_TYPE = SystemLog::TYPE_PAYPAL_PPCP;
|
2024-05-20 03:59:44 +02:00
|
|
|
|
2023-12-13 07:10:29 +01:00
|
|
|
/**
|
2024-05-20 03:59:44 +02:00
|
|
|
* Checks whether payments are enabled on the merchant account
|
|
|
|
*
|
2023-12-13 07:10:29 +01:00
|
|
|
* @return self
|
|
|
|
*/
|
2023-11-05 09:04:31 +01:00
|
|
|
private function checkPaymentsReceivable(): self
|
|
|
|
{
|
2023-11-06 10:01:27 +01:00
|
|
|
|
2023-11-26 08:41:42 +01:00
|
|
|
if($this->company_gateway->getConfigField('status') != 'activated') {
|
2023-11-06 10:01:27 +01:00
|
|
|
|
|
|
|
if (class_exists(\Modules\Admin\Services\PayPal\PayPalService::class)) {
|
|
|
|
$pp = new \Modules\Admin\Services\PayPal\PayPalService($this->company_gateway->company, $this->company_gateway->user);
|
|
|
|
$pp->updateMerchantStatus($this->company_gateway);
|
|
|
|
|
|
|
|
$this->company_gateway = $this->company_gateway->fresh();
|
|
|
|
$config = $this->company_gateway->getConfig();
|
|
|
|
|
2023-11-26 08:41:42 +01:00
|
|
|
if($config->status == 'activated') {
|
2023-11-06 10:01:27 +01:00
|
|
|
return $this;
|
2023-11-26 08:41:42 +01:00
|
|
|
}
|
2023-11-06 10:01:27 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-11-05 09:04:31 +01:00
|
|
|
throw new PaymentFailed('Unable to accept payments at this time, please contact PayPal for more information.', 401);
|
2023-11-06 07:41:20 +01:00
|
|
|
}
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2023-11-05 09:04:31 +01:00
|
|
|
return $this;
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2023-11-05 09:04:31 +01:00
|
|
|
}
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2023-12-13 07:10:29 +01:00
|
|
|
/**
|
|
|
|
* Presents the Payment View to the client
|
|
|
|
*
|
2024-04-26 13:17:15 +02:00
|
|
|
* @param array $data
|
|
|
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
2023-12-13 07:10:29 +01:00
|
|
|
*/
|
2023-10-16 03:05:19 +02:00
|
|
|
public function processPaymentView($data)
|
|
|
|
{
|
2024-06-13 08:52:23 +02:00
|
|
|
|
2023-11-05 09:04:31 +01:00
|
|
|
$this->init()->checkPaymentsReceivable();
|
2023-10-16 03:05:19 +02:00
|
|
|
|
|
|
|
$data['gateway'] = $this;
|
|
|
|
$this->payment_hash->data = array_merge((array) $this->payment_hash->data, ['amount' => $data['total']['amount_with_fee']]);
|
|
|
|
$this->payment_hash->save();
|
|
|
|
|
2023-10-29 10:09:15 +01:00
|
|
|
$data['client_id'] = config('ninja.paypal.client_id');
|
2023-10-16 06:48:45 +02:00
|
|
|
$data['token'] = $this->getClientToken();
|
2023-10-16 03:05:19 +02:00
|
|
|
$data['order_id'] = $this->createOrder($data);
|
2023-10-16 07:29:34 +02:00
|
|
|
$data['funding_source'] = $this->paypal_payment_method;
|
2023-10-18 04:31:04 +02:00
|
|
|
$data['gateway_type_id'] = $this->gateway_type_id;
|
2023-10-29 10:33:26 +01:00
|
|
|
$data['merchantId'] = $this->company_gateway->getConfigField('merchantId');
|
2023-11-30 07:44:34 +01:00
|
|
|
$data['currency'] = $this->client->currency()->code;
|
2024-06-13 08:52:23 +02:00
|
|
|
$data['guid'] = $this->risk_guid;
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2024-05-20 05:14:50 +02:00
|
|
|
if($this->gateway_type_id == 29)
|
2024-05-20 03:59:44 +02:00
|
|
|
return render('gateways.paypal.ppcp.card', $data);
|
|
|
|
else
|
|
|
|
return render('gateways.paypal.ppcp.pay', $data);
|
2023-10-16 06:48:45 +02:00
|
|
|
|
|
|
|
}
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2023-12-13 07:10:29 +01:00
|
|
|
/**
|
|
|
|
* Processes the payment response
|
|
|
|
*
|
|
|
|
* @param mixed $request
|
|
|
|
*/
|
2023-10-16 03:05:19 +02:00
|
|
|
public function processPaymentResponse($request)
|
|
|
|
{
|
2023-12-06 02:09:43 +01:00
|
|
|
|
2024-06-06 04:31:24 +02:00
|
|
|
nlog("response");
|
2024-06-09 01:08:31 +02:00
|
|
|
$r = false;
|
|
|
|
|
2023-10-18 04:31:04 +02:00
|
|
|
$request['gateway_response'] = str_replace("Error: ", "", $request['gateway_response']);
|
2023-10-16 07:23:04 +02:00
|
|
|
$response = json_decode($request['gateway_response'], true);
|
2023-10-16 08:00:37 +02:00
|
|
|
|
2024-06-06 04:31:24 +02:00
|
|
|
nlog($response);
|
|
|
|
|
2024-05-20 05:14:50 +02:00
|
|
|
if($request->has('token') && strlen($request->input('token')) > 2) {
|
|
|
|
return $this->processTokenPayment($request, $response);
|
|
|
|
}
|
|
|
|
|
2023-12-06 02:09:43 +01:00
|
|
|
//capture
|
2024-06-06 04:31:24 +02:00
|
|
|
$orderID = $response['orderID'] ?? $this->payment_hash->data->orderID;
|
2024-01-25 10:33:47 +01:00
|
|
|
|
2024-02-13 05:25:18 +01:00
|
|
|
if($this->company_gateway->require_shipping_address) {
|
2024-01-25 10:33:47 +01:00
|
|
|
|
2024-02-13 05:25:18 +01:00
|
|
|
$shipping_data =
|
2024-01-25 10:33:47 +01:00
|
|
|
[[
|
|
|
|
"op" => "replace",
|
|
|
|
"path" => "/purchase_units/@reference_id=='default'/shipping/address",
|
|
|
|
"value" => [
|
2024-04-26 13:17:15 +02:00
|
|
|
"address_line_1" => strlen($this->client->shipping_address1 ?? '') > 1 ? $this->client->shipping_address1 : $this->client->address1,
|
2024-01-25 10:33:47 +01:00
|
|
|
"address_line_2" => $this->client->shipping_address2,
|
2024-04-26 13:17:15 +02:00
|
|
|
"admin_area_2" => strlen($this->client->shipping_city ?? '') > 1 ? $this->client->shipping_city : $this->client->city,
|
|
|
|
"admin_area_1" => strlen($this->client->shipping_state ?? '') > 1 ? $this->client->shipping_state : $this->client->state,
|
|
|
|
"postal_code" => strlen($this->client->shipping_postal_code ?? '') > 1 ? $this->client->shipping_postal_code : $this->client->postal_code,
|
2024-01-25 10:33:47 +01:00
|
|
|
"country_code" => $this->client->present()->shipping_country_code(),
|
|
|
|
],
|
|
|
|
]];
|
2024-02-13 05:25:18 +01:00
|
|
|
|
2024-01-25 10:33:47 +01:00
|
|
|
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}", 'patch', $shipping_data);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2024-03-19 02:17:25 +01:00
|
|
|
try {
|
|
|
|
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']);
|
2024-05-24 02:38:07 +02:00
|
|
|
|
|
|
|
if($r->status() == 422) {
|
|
|
|
//handle conditions where the client may need to try again.
|
2024-06-06 04:31:24 +02:00
|
|
|
// return $this->handleRetry($r, $request);
|
|
|
|
|
|
|
|
$r = $this->handleDuplicateInvoiceId($orderID);
|
|
|
|
|
2024-05-24 02:38:07 +02:00
|
|
|
}
|
|
|
|
|
2024-03-19 02:17:25 +01:00
|
|
|
} catch(\Exception $e) {
|
|
|
|
|
|
|
|
//Rescue for duplicate invoice_id
|
|
|
|
if(stripos($e->getMessage(), 'DUPLICATE_INVOICE_ID') !== false) {
|
2024-06-06 04:31:24 +02:00
|
|
|
$r = $this->handleDuplicateInvoiceId($orderID);
|
2024-03-19 02:17:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2023-12-06 02:09:43 +01:00
|
|
|
|
|
|
|
$response = $r;
|
|
|
|
|
2024-06-06 04:31:24 +02:00
|
|
|
nlog("Process response =>");
|
|
|
|
nlog($response->json());
|
|
|
|
|
2023-10-18 04:31:04 +02:00
|
|
|
if(isset($response['status']) && $response['status'] == 'COMPLETED' && isset($response['purchase_units'])) {
|
2023-10-16 03:05:19 +02:00
|
|
|
|
2023-10-16 07:23:04 +02:00
|
|
|
$data = [
|
2023-10-18 04:31:04 +02:00
|
|
|
'payment_type' => $this->getPaymentMethod($request->gateway_type_id),
|
2023-12-06 02:09:43 +01:00
|
|
|
'amount' => $response['purchase_units'][0]['payments']['captures'][0]['amount']['value'],
|
2023-10-16 07:23:04 +02:00
|
|
|
'transaction_reference' => $response['purchase_units'][0]['payments']['captures'][0]['id'],
|
|
|
|
'gateway_type_id' => GatewayType::PAYPAL,
|
|
|
|
];
|
2023-10-16 03:05:19 +02:00
|
|
|
|
2023-10-16 07:23:04 +02:00
|
|
|
$payment = $this->createPayment($data, \App\Models\Payment::STATUS_COMPLETED);
|
2023-10-16 03:05:19 +02:00
|
|
|
|
2023-10-16 07:23:04 +02:00
|
|
|
SystemLogger::dispatch(
|
|
|
|
['response' => $response, 'data' => $data],
|
|
|
|
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
|
|
|
SystemLog::EVENT_GATEWAY_SUCCESS,
|
2024-05-20 05:14:50 +02:00
|
|
|
SystemLog::TYPE_PAYPAL_PPCP,
|
2023-10-16 07:23:04 +02:00
|
|
|
$this->client,
|
|
|
|
$this->client->company,
|
|
|
|
);
|
2024-05-24 02:38:07 +02:00
|
|
|
|
|
|
|
return response()->json(['redirect' => route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)], false)]);
|
2023-10-16 03:05:19 +02:00
|
|
|
|
2024-05-24 02:38:07 +02:00
|
|
|
// return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]);
|
2023-10-16 03:05:19 +02:00
|
|
|
|
2023-10-16 07:23:04 +02:00
|
|
|
} else {
|
2023-10-16 03:05:19 +02:00
|
|
|
|
2023-11-26 08:41:42 +01:00
|
|
|
if(isset($response['headers']) ?? false) {
|
2023-10-18 04:31:04 +02:00
|
|
|
unset($response['headers']);
|
2023-11-26 08:41:42 +01:00
|
|
|
}
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2023-10-16 07:23:04 +02:00
|
|
|
SystemLogger::dispatch(
|
|
|
|
['response' => $response],
|
|
|
|
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
|
|
|
SystemLog::EVENT_GATEWAY_FAILURE,
|
2024-05-20 05:14:50 +02:00
|
|
|
SystemLog::TYPE_PAYPAL_PPCP,
|
2023-10-16 07:23:04 +02:00
|
|
|
$this->client,
|
|
|
|
$this->client->company,
|
|
|
|
);
|
2023-10-16 03:05:19 +02:00
|
|
|
|
2023-10-18 04:31:04 +02:00
|
|
|
$message = $response['body']['details'][0]['description'] ?? 'Payment failed. Please try again.';
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2024-05-24 02:38:07 +02:00
|
|
|
return response()->json(['message' => $message], 400);
|
|
|
|
|
2023-10-16 07:23:04 +02:00
|
|
|
}
|
2023-10-16 03:05:19 +02:00
|
|
|
}
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2023-12-13 07:10:29 +01:00
|
|
|
public function getOrder(string $order_id)
|
|
|
|
{
|
|
|
|
$this->init();
|
2023-10-16 03:05:19 +02:00
|
|
|
|
2023-12-13 07:10:29 +01:00
|
|
|
$r = $this->gatewayRequest("/v2/checkout/orders/{$order_id}", 'get', ['body' => '']);
|
2023-11-22 04:06:51 +01:00
|
|
|
|
2023-12-13 07:10:29 +01:00
|
|
|
return $r->json();
|
|
|
|
}
|
2023-12-06 02:09:43 +01:00
|
|
|
|
2023-12-13 07:10:29 +01:00
|
|
|
/**
|
|
|
|
* Creates the PayPal Order object
|
|
|
|
*
|
|
|
|
* @param array $data
|
|
|
|
* @return string
|
|
|
|
*/
|
2024-05-20 03:59:44 +02:00
|
|
|
public function createOrder(array $data): string
|
2023-10-16 03:05:19 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
$_invoice = collect($this->payment_hash->data->invoices)->first();
|
|
|
|
|
|
|
|
$invoice = Invoice::withTrashed()->find($this->decodePrimaryKey($_invoice->invoice_id));
|
|
|
|
|
2023-11-26 08:41:42 +01:00
|
|
|
$description = collect($invoice->line_items)->map(function ($item) {
|
2023-10-23 13:10:41 +02:00
|
|
|
return $item->notes;
|
|
|
|
})->implode("\n");
|
|
|
|
|
2023-10-16 03:05:19 +02:00
|
|
|
$order = [
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2023-11-06 13:31:48 +01:00
|
|
|
"intent" => "CAPTURE",
|
2024-05-20 03:59:44 +02:00
|
|
|
"payment_source" => $this->getPaymentSource(),
|
2023-11-06 13:31:48 +01:00
|
|
|
"purchase_units" => [
|
|
|
|
[
|
2023-12-13 07:10:29 +01:00
|
|
|
"custom_id" => $this->payment_hash->hash,
|
|
|
|
"description" => ctrans('texts.invoice_number').'# '.$invoice->number,
|
2023-11-06 13:31:48 +01:00
|
|
|
"invoice_id" => $invoice->number,
|
|
|
|
"payee" => [
|
|
|
|
"merchant_id" => $this->company_gateway->getConfigField('merchantId'),
|
|
|
|
],
|
2023-10-19 07:10:51 +02:00
|
|
|
"payment_instruction" => [
|
2023-10-19 08:26:52 +02:00
|
|
|
"disbursement_mode" => "INSTANT",
|
|
|
|
],
|
2023-11-06 13:31:48 +01:00
|
|
|
"amount" => [
|
|
|
|
"value" => (string)$data['amount_with_fee'],
|
2024-01-14 05:05:00 +01:00
|
|
|
"currency_code" => $this->client->currency()->code,
|
2023-11-06 13:31:48 +01:00
|
|
|
"breakdown" => [
|
|
|
|
"item_total" => [
|
|
|
|
"currency_code" => $this->client->currency()->code,
|
|
|
|
"value" => (string)$data['amount_with_fee']
|
|
|
|
]
|
|
|
|
]
|
|
|
|
],
|
2024-01-14 05:05:00 +01:00
|
|
|
"items" => [
|
2023-11-06 13:31:48 +01:00
|
|
|
[
|
|
|
|
"name" => ctrans('texts.invoice_number').'# '.$invoice->number,
|
2024-01-27 05:43:37 +01:00
|
|
|
"description" => mb_substr($description, 0, 127),
|
2023-11-06 13:31:48 +01:00
|
|
|
"quantity" => "1",
|
|
|
|
"unit_amount" => [
|
|
|
|
"currency_code" => $this->client->currency()->code,
|
|
|
|
"value" => (string)$data['amount_with_fee']
|
|
|
|
],
|
|
|
|
],
|
|
|
|
],
|
2023-10-19 08:26:52 +02:00
|
|
|
],
|
2023-11-06 13:31:48 +01:00
|
|
|
]
|
|
|
|
];
|
2023-11-24 09:23:45 +01:00
|
|
|
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2023-11-26 08:41:42 +01:00
|
|
|
if($shipping = $this->getShippingAddress()) {
|
2024-01-23 21:31:06 +01:00
|
|
|
$order['purchase_units'][0]["shipping"] = $shipping;
|
2023-11-24 09:23:45 +01:00
|
|
|
}
|
|
|
|
|
2024-05-20 05:14:50 +02:00
|
|
|
if(isset($data['payment_source'])) {
|
|
|
|
$order['payment_source'] = $data['payment_source'];
|
|
|
|
}
|
|
|
|
|
2023-10-16 03:05:19 +02:00
|
|
|
$r = $this->gatewayRequest('/v2/checkout/orders', 'post', $order);
|
|
|
|
|
2024-06-06 01:21:23 +02:00
|
|
|
$this->payment_hash->withData("orderID", $r->json()['id']);
|
|
|
|
|
2023-10-16 03:05:19 +02:00
|
|
|
return $r->json()['id'];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-12-13 07:10:29 +01:00
|
|
|
/**
|
2024-05-20 03:59:44 +02:00
|
|
|
* processTokenPayment
|
2023-12-13 07:10:29 +01:00
|
|
|
*
|
2024-05-20 03:59:44 +02:00
|
|
|
* With PayPal and token payments, the order needs to be
|
|
|
|
* deleted and then created with the payment source that
|
|
|
|
* has been selected by the client.
|
|
|
|
*
|
|
|
|
* This method handle the deletion of the current paypal order,
|
|
|
|
* and the automatic payment of the order with the selected payment source.
|
|
|
|
*
|
|
|
|
* @param mixed $request
|
|
|
|
* @param array $response
|
|
|
|
* @return void
|
2023-12-13 07:10:29 +01:00
|
|
|
*/
|
2024-05-20 03:59:44 +02:00
|
|
|
public function processTokenPayment($request, array $response) {
|
|
|
|
|
2024-06-09 07:56:05 +02:00
|
|
|
/** @var \App\Models\ClientGatewayToken $cgt */
|
2024-05-20 03:59:44 +02:00
|
|
|
$cgt = ClientGatewayToken::where('client_id', $this->client->id)
|
|
|
|
->where('token', $request['token'])
|
|
|
|
->firstOrFail();
|
|
|
|
|
|
|
|
$orderId = $response['orderID'];
|
|
|
|
$r = $this->gatewayRequest("/v1/checkout/orders/{$orderId}/", 'delete', ['body' => '']);
|
|
|
|
|
|
|
|
$data['amount_with_fee'] = $this->payment_hash->data->amount_with_fee;
|
|
|
|
$data["payment_source"] = [
|
|
|
|
"card" => [
|
|
|
|
"vault_id" => $cgt->token,
|
|
|
|
"stored_credential" => [
|
|
|
|
"payment_initiator" => "MERCHANT",
|
|
|
|
"payment_type" => "UNSCHEDULED",
|
|
|
|
"usage" => "SUBSEQUENT",
|
|
|
|
],
|
|
|
|
],
|
|
|
|
];
|
|
|
|
|
|
|
|
$orderId = $this->createOrder($data);
|
|
|
|
|
|
|
|
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderId}", 'get', ['body' => '']);
|
|
|
|
|
|
|
|
$response = $r->json();
|
|
|
|
|
|
|
|
$data = [
|
|
|
|
'payment_type' => $this->getPaymentMethod($request->gateway_type_id),
|
|
|
|
'amount' => $response['purchase_units'][0]['payments']['captures'][0]['amount']['value'],
|
|
|
|
'transaction_reference' => $response['purchase_units'][0]['payments']['captures'][0]['id'],
|
|
|
|
'gateway_type_id' => $this->gateway_type_id,
|
|
|
|
];
|
2023-10-16 03:05:19 +02:00
|
|
|
|
2024-05-20 03:59:44 +02:00
|
|
|
$payment = $this->createPayment($data, \App\Models\Payment::STATUS_COMPLETED);
|
2023-10-16 03:05:19 +02:00
|
|
|
|
2023-12-06 02:09:43 +01:00
|
|
|
SystemLogger::dispatch(
|
2024-05-20 03:59:44 +02:00
|
|
|
['response' => $response, 'data' => $data],
|
2023-12-06 02:09:43 +01:00
|
|
|
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
2024-05-20 03:59:44 +02:00
|
|
|
SystemLog::EVENT_GATEWAY_SUCCESS,
|
2024-05-20 05:14:50 +02:00
|
|
|
SystemLog::TYPE_PAYPAL_PPCP,
|
2023-12-06 02:09:43 +01:00
|
|
|
$this->client,
|
|
|
|
$this->client->company,
|
|
|
|
);
|
|
|
|
|
2024-05-20 03:59:44 +02:00
|
|
|
return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]);
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2023-10-16 03:05:19 +02:00
|
|
|
}
|
2024-06-13 08:52:23 +02:00
|
|
|
|
|
|
|
public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash)
|
|
|
|
{
|
|
|
|
$data = [];
|
|
|
|
$this->payment_hash = $payment_hash;
|
|
|
|
|
|
|
|
$data['amount_with_fee'] = $this->payment_hash->data->amount_with_fee;
|
|
|
|
$data["payment_source"] = [
|
|
|
|
"card" => [
|
|
|
|
"vault_id" => $cgt->token,
|
|
|
|
"stored_credential" => [
|
|
|
|
"payment_initiator" => "MERCHANT",
|
|
|
|
"payment_type" => "UNSCHEDULED",
|
|
|
|
"usage" => "SUBSEQUENT",
|
|
|
|
],
|
|
|
|
],
|
|
|
|
];
|
|
|
|
|
|
|
|
$orderId = $this->createOrder($data);
|
|
|
|
|
|
|
|
$r = false;
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderId}", 'get', ['body' => '']);
|
|
|
|
|
|
|
|
if($r->status() == 422) {
|
|
|
|
//handle conditions where the client may need to try again.
|
|
|
|
|
|
|
|
$r = $this->handleDuplicateInvoiceId($orderId);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch(\Exception $e) {
|
|
|
|
|
|
|
|
//Rescue for duplicate invoice_id
|
|
|
|
if(stripos($e->getMessage(), 'DUPLICATE_INVOICE_ID') !== false) {
|
|
|
|
|
|
|
|
|
|
|
|
$r = $this->handleDuplicateInvoiceId($orderId);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
$response = $r->json();
|
|
|
|
|
|
|
|
$data = [
|
|
|
|
'payment_type' => $this->getPaymentMethod((string)$cgt->gateway_type_id),
|
|
|
|
'amount' => $response['purchase_units'][0]['payments']['captures'][0]['amount']['value'],
|
|
|
|
'transaction_reference' => $response['purchase_units'][0]['payments']['captures'][0]['id'],
|
|
|
|
'gateway_type_id' => $this->gateway_type_id,
|
|
|
|
];
|
|
|
|
|
|
|
|
$payment = $this->createPayment($data, \App\Models\Payment::STATUS_COMPLETED);
|
|
|
|
|
|
|
|
SystemLogger::dispatch(
|
|
|
|
['response' => $response, 'data' => $data],
|
|
|
|
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
|
|
|
SystemLog::EVENT_GATEWAY_SUCCESS,
|
|
|
|
SystemLog::TYPE_PAYPAL_PPCP,
|
|
|
|
$this->client,
|
|
|
|
$this->client->company,
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2024-05-20 05:14:50 +02:00
|
|
|
}
|